From 311157c3c6849e8efccd88f7594bb34c570a6780 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Thu, 25 Sep 2014 13:22:55 +0300 Subject: ANGLE: Upgrade to 2.1~abce76206141 Upgrade to address issues discovered since the last upgrade. Patch notes: 0000-General-fixes-for-ANGLE-2.1.patch added removal of the unused third-party tracing functions 0003-Fix-compilation-with-MinGW-gcc-64-bit.patch removed as it is no longer needed 0011-ANGLE-Fix-compilation-error-on-MinGW-caused-by-trace.patch removed as it is no longer needed 0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch now supports MinGW 64-bit [ChangeLog][Third-party libraries] ANGLE updated to 2.1~f8602ad91e4f Task-number: QTBUG-40649 Task-number: QTBUG-40658 Task-number: QTBUG-41031 Task-number: QTBUG-41081 Task-number: QTBUG-41308 Task-number: QTBUG-41563 Change-Id: I9f776c8d5cb94ddb12d608a8d5630bfc54437bea Reviewed-by: Friedemann Kleint Reviewed-by: Oliver Wolff Reviewed-by: Kai Koehne --- src/3rdparty/angle/src/commit.h | 4 +- src/3rdparty/angle/src/common/RefCountObject.h | 4 +- src/3rdparty/angle/src/common/angleutils.cpp | 37 + src/3rdparty/angle/src/common/angleutils.h | 8 +- src/3rdparty/angle/src/common/blocklayout.cpp | 44 +- src/3rdparty/angle/src/common/blocklayout.h | 7 +- src/3rdparty/angle/src/common/debug.cpp | 26 +- src/3rdparty/angle/src/common/debug.h | 4 + src/3rdparty/angle/src/common/event_tracer.cpp | 49 - src/3rdparty/angle/src/common/event_tracer.h | 43 - src/3rdparty/angle/src/common/mathutil.cpp | 1 + src/3rdparty/angle/src/common/mathutil.h | 18 +- src/3rdparty/angle/src/common/platform.h | 20 +- src/3rdparty/angle/src/common/shadervars.h | 157 - .../angle/src/compiler/translator/BaseTypes.h | 33 +- .../compiler/translator/BuiltInFunctionEmulator.h | 2 +- .../angle/src/compiler/translator/Compiler.cpp | 26 +- .../angle/src/compiler/translator/Compiler.h | 13 +- .../src/compiler/translator/DetectCallDepth.h | 2 +- .../src/compiler/translator/DetectDiscontinuity.h | 2 +- .../src/compiler/translator/FlagStd140Structs.h | 2 +- .../angle/src/compiler/translator/HashNames.h | 2 +- .../angle/src/compiler/translator/Initialize.cpp | 2 +- .../src/compiler/translator/InitializeVariables.h | 2 +- .../angle/src/compiler/translator/IntermNode.cpp | 1107 +++++++ .../angle/src/compiler/translator/IntermNode.h | 772 +++++ .../src/compiler/translator/IntermTraverse.cpp | 2 +- .../angle/src/compiler/translator/Intermediate.cpp | 1093 +------ .../angle/src/compiler/translator/LoopInfo.h | 2 +- .../angle/src/compiler/translator/NodeSearch.h | 2 +- .../src/compiler/translator/OutputGLSLBase.cpp | 14 +- .../angle/src/compiler/translator/OutputGLSLBase.h | 2 +- .../angle/src/compiler/translator/OutputHLSL.cpp | 74 +- .../angle/src/compiler/translator/OutputHLSL.h | 16 +- .../angle/src/compiler/translator/ParseContext.cpp | 75 +- .../angle/src/compiler/translator/ParseContext.h | 7 +- .../src/compiler/translator/QualifierAlive.cpp | 2 +- .../compiler/translator/RegenerateStructNames.cpp | 82 + .../compiler/translator/RegenerateStructNames.h | 40 + .../angle/src/compiler/translator/RemoveTree.cpp | 2 +- .../angle/src/compiler/translator/RenameFunction.h | 2 +- .../src/compiler/translator/RewriteElseBlocks.h | 2 +- .../ScalarizeVecAndMatConstructorArgs.cpp | 11 + .../translator/ScalarizeVecAndMatConstructorArgs.h | 12 +- .../angle/src/compiler/translator/SearchSymbol.h | 2 +- .../angle/src/compiler/translator/ShaderLang.cpp | 124 +- .../angle/src/compiler/translator/ShaderVars.cpp | 166 + .../src/compiler/translator/StructureHLSL.cpp | 35 +- .../angle/src/compiler/translator/StructureHLSL.h | 13 +- .../angle/src/compiler/translator/SymbolTable.cpp | 8 +- .../angle/src/compiler/translator/SymbolTable.h | 14 +- .../src/compiler/translator/TranslatorHLSL.cpp | 8 +- .../angle/src/compiler/translator/TranslatorHLSL.h | 1 - .../angle/src/compiler/translator/Types.cpp | 32 + src/3rdparty/angle/src/compiler/translator/Types.h | 11 + .../src/compiler/translator/UnfoldShortCircuit.h | 2 +- .../compiler/translator/UnfoldShortCircuitAST.h | 2 +- .../angle/src/compiler/translator/UniformHLSL.cpp | 76 +- .../angle/src/compiler/translator/UniformHLSL.h | 9 +- .../src/compiler/translator/ValidateLimitations.h | 2 +- .../src/compiler/translator/ValidateOutputs.h | 2 +- .../angle/src/compiler/translator/VariableInfo.cpp | 197 +- .../angle/src/compiler/translator/VariableInfo.h | 37 +- .../src/compiler/translator/VariablePacker.cpp | 8 +- .../angle/src/compiler/translator/VersionGLSL.cpp | 3 + .../angle/src/compiler/translator/VersionGLSL.h | 2 +- .../compiler/translator/depgraph/DependencyGraph.h | 2 +- .../angle/src/compiler/translator/glslang.y | 58 +- .../angle/src/compiler/translator/intermOut.cpp | 3 +- .../angle/src/compiler/translator/intermediate.h | 806 +---- .../src/compiler/translator/localintermediate.h | 67 - .../timing/RestrictFragmentShaderTiming.h | 2 +- .../translator/timing/RestrictVertexShaderTiming.h | 2 +- .../angle/src/compiler/translator/util.cpp | 53 +- src/3rdparty/angle/src/compiler/translator/util.h | 28 +- src/3rdparty/angle/src/libEGL/Display.cpp | 5 +- src/3rdparty/angle/src/libEGL/libEGL.cpp | 12 +- src/3rdparty/angle/src/libEGL/main.cpp | 4 +- src/3rdparty/angle/src/libEGL/main.h | 2 - src/3rdparty/angle/src/libGLESv2/BinaryStream.h | 4 + src/3rdparty/angle/src/libGLESv2/Buffer.cpp | 67 +- src/3rdparty/angle/src/libGLESv2/Buffer.h | 22 +- src/3rdparty/angle/src/libGLESv2/Caps.cpp | 94 +- src/3rdparty/angle/src/libGLESv2/Caps.h | 53 +- src/3rdparty/angle/src/libGLESv2/Context.cpp | 974 +++--- src/3rdparty/angle/src/libGLESv2/Context.h | 114 +- src/3rdparty/angle/src/libGLESv2/DynamicHLSL.cpp | 1122 ------- src/3rdparty/angle/src/libGLESv2/DynamicHLSL.h | 96 - src/3rdparty/angle/src/libGLESv2/Error.cpp | 48 + src/3rdparty/angle/src/libGLESv2/Error.h | 39 + src/3rdparty/angle/src/libGLESv2/Fence.cpp | 3 +- .../angle/src/libGLESv2/Float16ToFloat32.cpp | 1 - src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp | 163 +- src/3rdparty/angle/src/libGLESv2/Framebuffer.h | 28 +- .../angle/src/libGLESv2/FramebufferAttachment.cpp | 385 +-- .../angle/src/libGLESv2/FramebufferAttachment.h | 157 +- .../angle/src/libGLESv2/HandleAllocator.cpp | 1 - src/3rdparty/angle/src/libGLESv2/HandleAllocator.h | 4 +- src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp | 57 + src/3rdparty/angle/src/libGLESv2/ImageIndex.h | 41 + src/3rdparty/angle/src/libGLESv2/Program.cpp | 23 +- src/3rdparty/angle/src/libGLESv2/Program.h | 22 +- src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp | 822 +++-- src/3rdparty/angle/src/libGLESv2/ProgramBinary.h | 133 +- src/3rdparty/angle/src/libGLESv2/Query.cpp | 33 +- src/3rdparty/angle/src/libGLESv2/Query.h | 17 +- src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp | 35 +- src/3rdparty/angle/src/libGLESv2/Renderbuffer.h | 6 +- .../angle/src/libGLESv2/ResourceManager.cpp | 31 +- src/3rdparty/angle/src/libGLESv2/ResourceManager.h | 12 +- src/3rdparty/angle/src/libGLESv2/Sampler.cpp | 1 - src/3rdparty/angle/src/libGLESv2/Shader.cpp | 476 +-- src/3rdparty/angle/src/libGLESv2/Shader.h | 135 +- src/3rdparty/angle/src/libGLESv2/State.cpp | 124 +- src/3rdparty/angle/src/libGLESv2/State.h | 24 +- src/3rdparty/angle/src/libGLESv2/Texture.cpp | 787 +++-- src/3rdparty/angle/src/libGLESv2/Texture.h | 154 +- .../angle/src/libGLESv2/TransformFeedback.cpp | 10 +- .../angle/src/libGLESv2/TransformFeedback.h | 9 +- src/3rdparty/angle/src/libGLESv2/Uniform.cpp | 1 - src/3rdparty/angle/src/libGLESv2/Uniform.h | 12 +- src/3rdparty/angle/src/libGLESv2/VertexArray.cpp | 1 - src/3rdparty/angle/src/libGLESv2/VertexArray.h | 2 + .../angle/src/libGLESv2/VertexAttribute.cpp | 1 - src/3rdparty/angle/src/libGLESv2/angletypes.cpp | 1 - src/3rdparty/angle/src/libGLESv2/angletypes.h | 12 +- src/3rdparty/angle/src/libGLESv2/constants.h | 4 - src/3rdparty/angle/src/libGLESv2/formatutils.cpp | 1581 ++------- src/3rdparty/angle/src/libGLESv2/formatutils.h | 98 +- src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp | 3338 +++++++++++--------- src/3rdparty/angle/src/libGLESv2/libGLESv2.def | 3 - .../angle/src/libGLESv2/libGLESv2_mingw32.def | 3 - src/3rdparty/angle/src/libGLESv2/libGLESv2d.def | 3 - .../angle/src/libGLESv2/libGLESv2d_mingw32.def | 3 - src/3rdparty/angle/src/libGLESv2/main.cpp | 44 +- src/3rdparty/angle/src/libGLESv2/main.h | 4 +- src/3rdparty/angle/src/libGLESv2/precompiled.cpp | 9 - src/3rdparty/angle/src/libGLESv2/precompiled.h | 32 - .../angle/src/libGLESv2/queryconversions.cpp | 1 - .../angle/src/libGLESv2/renderer/BufferImpl.h | 10 +- .../angle/src/libGLESv2/renderer/Image.cpp | 1 - src/3rdparty/angle/src/libGLESv2/renderer/Image.h | 2 + .../src/libGLESv2/renderer/IndexRangeCache.cpp | 57 +- .../angle/src/libGLESv2/renderer/IndexRangeCache.h | 17 +- .../angle/src/libGLESv2/renderer/ProgramImpl.h | 58 + .../angle/src/libGLESv2/renderer/QueryImpl.h | 21 +- .../angle/src/libGLESv2/renderer/Renderer.cpp | 10 +- .../angle/src/libGLESv2/renderer/Renderer.h | 126 +- .../src/libGLESv2/renderer/ShaderExecutable.h | 3 + .../angle/src/libGLESv2/renderer/ShaderImpl.h | 54 + .../angle/src/libGLESv2/renderer/SwapChain.h | 8 +- .../angle/src/libGLESv2/renderer/TextureImpl.h | 134 +- .../src/libGLESv2/renderer/TransformFeedbackImpl.h | 31 + .../angle/src/libGLESv2/renderer/copyimage.cpp | 11 +- .../angle/src/libGLESv2/renderer/copyimage.h | 25 +- .../angle/src/libGLESv2/renderer/copyimage.inl | 32 + .../angle/src/libGLESv2/renderer/copyvertex.h | 298 +- .../angle/src/libGLESv2/renderer/copyvertex.inl | 288 ++ .../angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp | 3 +- .../angle/src/libGLESv2/renderer/d3d/BufferD3D.h | 4 - .../src/libGLESv2/renderer/d3d/DynamicHLSL.cpp | 1144 +++++++ .../angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h | 104 + .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp | 25 +- .../angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp | 1 - .../angle/src/libGLESv2/renderer/d3d/ImageD3D.h | 21 +- .../src/libGLESv2/renderer/d3d/IndexBuffer.cpp | 41 +- .../angle/src/libGLESv2/renderer/d3d/IndexBuffer.h | 27 +- .../libGLESv2/renderer/d3d/IndexDataManager.cpp | 296 +- .../src/libGLESv2/renderer/d3d/IndexDataManager.h | 17 +- .../src/libGLESv2/renderer/d3d/MemoryBuffer.cpp | 2 + .../src/libGLESv2/renderer/d3d/MemoryBuffer.h | 1 + .../src/libGLESv2/renderer/d3d/ProgramD3D.cpp | 205 ++ .../angle/src/libGLESv2/renderer/d3d/ProgramD3D.h | 87 + .../angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp | 457 +++ .../angle/src/libGLESv2/renderer/d3d/ShaderD3D.h | 94 + .../src/libGLESv2/renderer/d3d/TextureD3D.cpp | 990 ++---- .../angle/src/libGLESv2/renderer/d3d/TextureD3D.h | 221 +- .../src/libGLESv2/renderer/d3d/TextureStorage.cpp | 160 +- .../src/libGLESv2/renderer/d3d/TextureStorage.h | 114 +- .../renderer/d3d/TransformFeedbackD3D.cpp | 38 + .../libGLESv2/renderer/d3d/TransformFeedbackD3D.h | 32 + .../src/libGLESv2/renderer/d3d/VertexBuffer.cpp | 101 +- .../src/libGLESv2/renderer/d3d/VertexBuffer.h | 40 +- .../libGLESv2/renderer/d3d/VertexDataManager.cpp | 357 ++- .../src/libGLESv2/renderer/d3d/VertexDataManager.h | 29 +- .../src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp | 48 +- .../src/libGLESv2/renderer/d3d/d3d11/Blit11.h | 7 +- .../src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp | 231 +- .../src/libGLESv2/renderer/d3d/d3d11/Buffer11.h | 15 +- .../src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp | 93 +- .../src/libGLESv2/renderer/d3d/d3d11/Clear11.h | 6 +- .../src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp | 3 +- .../src/libGLESv2/renderer/d3d/d3d11/Image11.cpp | 203 +- .../src/libGLESv2/renderer/d3d/d3d11/Image11.h | 24 +- .../libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp | 99 +- .../libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h | 10 +- .../renderer/d3d/d3d11/InputLayoutCache.cpp | 21 +- .../renderer/d3d/d3d11/InputLayoutCache.h | 10 +- .../renderer/d3d/d3d11/PixelTransfer11.cpp | 19 +- .../libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h | 4 + .../src/libGLESv2/renderer/d3d/d3d11/Query11.cpp | 129 +- .../src/libGLESv2/renderer/d3d/d3d11/Query11.h | 15 +- .../renderer/d3d/d3d11/RenderStateCache.cpp | 86 +- .../renderer/d3d/d3d11/RenderStateCache.h | 11 +- .../renderer/d3d/d3d11/RenderTarget11.cpp | 48 +- .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 1051 +++--- .../src/libGLESv2/renderer/d3d/d3d11/Renderer11.h | 143 +- .../renderer/d3d/d3d11/ShaderExecutable11.cpp | 2 - .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp | 51 +- .../renderer/d3d/d3d11/TextureStorage11.cpp | 682 +++- .../renderer/d3d/d3d11/TextureStorage11.h | 85 +- .../renderer/d3d/d3d11/VertexBuffer11.cpp | 152 +- .../libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h | 14 +- .../libGLESv2/renderer/d3d/d3d11/formatutils11.cpp | 1725 ++++------ .../libGLESv2/renderer/d3d/d3d11/formatutils11.h | 81 +- .../renderer/d3d/d3d11/renderer11_utils.cpp | 564 +++- .../renderer/d3d/d3d11/renderer11_utils.h | 12 + .../src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp | 23 +- .../angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h | 9 +- .../src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp | 51 +- .../src/libGLESv2/renderer/d3d/d3d9/Buffer9.h | 11 +- .../src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp | 3 +- .../src/libGLESv2/renderer/d3d/d3d9/Image9.cpp | 119 +- .../angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h | 14 +- .../libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp | 120 +- .../src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h | 10 +- .../src/libGLESv2/renderer/d3d/d3d9/Query9.cpp | 103 +- .../angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h | 14 +- .../libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp | 32 +- .../src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 851 +++-- .../src/libGLESv2/renderer/d3d/d3d9/Renderer9.h | 138 +- .../src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h | 4 + .../renderer/d3d/d3d9/ShaderExecutable9.cpp | 1 - .../src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp | 16 +- .../renderer/d3d/d3d9/TextureStorage9.cpp | 80 +- .../libGLESv2/renderer/d3d/d3d9/TextureStorage9.h | 15 +- .../libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp | 189 +- .../libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h | 20 +- .../renderer/d3d/d3d9/VertexDeclarationCache.cpp | 47 +- .../renderer/d3d/d3d9/VertexDeclarationCache.h | 3 +- .../libGLESv2/renderer/d3d/d3d9/formatutils9.cpp | 734 ++--- .../src/libGLESv2/renderer/d3d/d3d9/formatutils9.h | 71 +- .../renderer/d3d/d3d9/renderer9_utils.cpp | 165 +- .../libGLESv2/renderer/d3d/d3d9/renderer9_utils.h | 20 +- .../angle/src/libGLESv2/renderer/loadimage.cpp | 1 - .../angle/src/libGLESv2/renderer/loadimageSSE2.cpp | 1 - .../src/libGLESv2/renderer/vertexconversion.h | 22 +- src/3rdparty/angle/src/libGLESv2/validationES.cpp | 757 +++-- src/3rdparty/angle/src/libGLESv2/validationES.h | 67 +- src/3rdparty/angle/src/libGLESv2/validationES2.cpp | 314 +- src/3rdparty/angle/src/libGLESv2/validationES2.h | 10 +- src/3rdparty/angle/src/libGLESv2/validationES3.cpp | 785 ++++- src/3rdparty/angle/src/libGLESv2/validationES3.h | 18 +- .../src/third_party/compiler/ArrayBoundsClamper.h | 2 +- .../src/third_party/trace_event/trace_event.h | 828 ----- 255 files changed, 17204 insertions(+), 17010 deletions(-) create mode 100644 src/3rdparty/angle/src/common/angleutils.cpp delete mode 100644 src/3rdparty/angle/src/common/event_tracer.cpp delete mode 100644 src/3rdparty/angle/src/common/event_tracer.h delete mode 100644 src/3rdparty/angle/src/common/shadervars.h create mode 100644 src/3rdparty/angle/src/compiler/translator/IntermNode.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/IntermNode.h create mode 100644 src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h create mode 100644 src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/localintermediate.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/DynamicHLSL.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/DynamicHLSL.h create mode 100644 src/3rdparty/angle/src/libGLESv2/Error.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/Error.h create mode 100644 src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/ImageIndex.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/precompiled.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/precompiled.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.inl create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h delete mode 100644 src/3rdparty/angle/src/third_party/trace_event/trace_event.h (limited to 'src/3rdparty/angle/src') diff --git a/src/3rdparty/angle/src/commit.h b/src/3rdparty/angle/src/commit.h index e1378309a4..a2e761b131 100644 --- a/src/3rdparty/angle/src/commit.h +++ b/src/3rdparty/angle/src/commit.h @@ -7,6 +7,6 @@ // This is a default commit hash header, when git is not available. // -#define ANGLE_COMMIT_HASH "07d49ef5350a" +#define ANGLE_COMMIT_HASH "abce76206141" #define ANGLE_COMMIT_HASH_SIZE 12 -#define ANGLE_COMMIT_DATE "2014-07-25 16:01:42 +0000" +#define ANGLE_COMMIT_DATE "2014-09-23 19:37:05 +0000" diff --git a/src/3rdparty/angle/src/common/RefCountObject.h b/src/3rdparty/angle/src/common/RefCountObject.h index 8635aa59d8..6eeaee1928 100644 --- a/src/3rdparty/angle/src/common/RefCountObject.h +++ b/src/3rdparty/angle/src/common/RefCountObject.h @@ -12,11 +12,11 @@ #ifndef COMMON_REFCOUNTOBJECT_H_ #define COMMON_REFCOUNTOBJECT_H_ -#include +#include "common/debug.h" #include "angle_gl.h" -#include "common/debug.h" +#include class RefCountObject { diff --git a/src/3rdparty/angle/src/common/angleutils.cpp b/src/3rdparty/angle/src/common/angleutils.cpp new file mode 100644 index 0000000000..2673abf30a --- /dev/null +++ b/src/3rdparty/angle/src/common/angleutils.cpp @@ -0,0 +1,37 @@ +// +// 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/angleutils.h" + +#include + +std::string FormatString(const char *fmt, va_list vararg) +{ + static std::vector buffer(512); + + // Attempt to just print to the current buffer + int len = vsnprintf(&buffer[0], buffer.size(), fmt, vararg); + if (len < 0 || static_cast(len) >= buffer.size()) + { + // Buffer was not large enough, calculate the required size and resize the buffer + len = vsnprintf(NULL, 0, fmt, vararg); + buffer.resize(len + 1); + + // Print again + vsnprintf(&buffer[0], buffer.size(), fmt, vararg); + } + + return std::string(buffer.data(), len); +} + +std::string FormatString(const char *fmt, ...) +{ + va_list vararg; + va_start(vararg, fmt); + std::string result = FormatString(fmt, vararg); + va_end(vararg); + return result; +} diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h index d94b4f5ff9..ddbbd5f501 100644 --- a/src/3rdparty/angle/src/common/angleutils.h +++ b/src/3rdparty/angle/src/common/angleutils.h @@ -16,6 +16,7 @@ #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 @@ -23,8 +24,8 @@ TypeName(const TypeName&); \ void operator=(const TypeName&) -template -inline unsigned int ArraySize(T(&)[N]) +template +inline size_t ArraySize(T(&)[N]) { return N; } @@ -131,6 +132,9 @@ inline std::string Str(int i) return strstr.str(); } +std::string FormatString(const char *fmt, va_list vararg); +std::string FormatString(const char *fmt, ...); + #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf #endif diff --git a/src/3rdparty/angle/src/common/blocklayout.cpp b/src/3rdparty/angle/src/common/blocklayout.cpp index 7db6e980f1..e3b2d43566 100644 --- a/src/3rdparty/angle/src/common/blocklayout.cpp +++ b/src/3rdparty/angle/src/common/blocklayout.cpp @@ -8,7 +8,6 @@ // #include "common/blocklayout.h" -#include "common/shadervars.h" #include "common/mathutil.h" #include "common/utilities.h" @@ -20,46 +19,7 @@ BlockLayoutEncoder::BlockLayoutEncoder() { } -void BlockLayoutEncoder::encodeInterfaceBlockFields(const std::vector &fields) -{ - for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) - { - const InterfaceBlockField &variable = fields[fieldIndex]; - - if (variable.fields.size() > 0) - { - const unsigned int elementCount = std::max(1u, variable.arraySize); - - for (unsigned int elementIndex = 0; elementIndex < elementCount; elementIndex++) - { - enterAggregateType(); - encodeInterfaceBlockFields(variable.fields); - exitAggregateType(); - } - } - else - { - encodeInterfaceBlockField(variable); - } - } -} - -BlockMemberInfo BlockLayoutEncoder::encodeInterfaceBlockField(const InterfaceBlockField &field) -{ - int arrayStride; - int matrixStride; - - ASSERT(field.fields.empty()); - getBlockLayoutInfo(field.type, field.arraySize, field.isRowMajorMatrix, &arrayStride, &matrixStride); - - const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, field.isRowMajorMatrix); - - advanceOffset(field.type, field.arraySize, field.isRowMajorMatrix, arrayStride, matrixStride); - - return memberInfo; -} - -void BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix) +BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix) { int arrayStride; int matrixStride; @@ -69,6 +29,8 @@ void BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool is const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix); advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride); + + return memberInfo; } void BlockLayoutEncoder::nextRegister() diff --git a/src/3rdparty/angle/src/common/blocklayout.h b/src/3rdparty/angle/src/common/blocklayout.h index 3a1ab5ccb0..d46ac6e547 100644 --- a/src/3rdparty/angle/src/common/blocklayout.h +++ b/src/3rdparty/angle/src/common/blocklayout.h @@ -10,10 +10,11 @@ #ifndef COMMON_BLOCKLAYOUT_H_ #define COMMON_BLOCKLAYOUT_H_ +#include #include + #include "angle_gl.h" #include -#include namespace sh { @@ -48,9 +49,7 @@ class BlockLayoutEncoder public: BlockLayoutEncoder(); - void encodeInterfaceBlockFields(const std::vector &fields); - BlockMemberInfo encodeInterfaceBlockField(const InterfaceBlockField &field); - void encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix); + BlockMemberInfo encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix); size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; } size_t getCurrentRegister() const { return mCurrentOffset / ComponentsPerRegister; } diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp index d6eecf7157..dcad327564 100644 --- a/src/3rdparty/angle/src/common/debug.cpp +++ b/src/3rdparty/angle/src/common/debug.cpp @@ -8,6 +8,7 @@ #include "common/debug.h" #include "common/platform.h" +#include "common/angleutils.h" #include #include @@ -25,22 +26,7 @@ typedef void (*PerfOutputFunction)(unsigned int, const wchar_t*); static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const char *format, va_list vararg) { #if defined(ANGLE_ENABLE_PERF) || defined(ANGLE_ENABLE_TRACE) - static std::vector asciiMessageBuffer(512); - - // Attempt to just print to the current buffer - int len = vsnprintf(&asciiMessageBuffer[0], asciiMessageBuffer.size(), format, vararg); - if (len < 0 || static_cast(len) >= asciiMessageBuffer.size()) - { - // Buffer was not large enough, calculate the required size and resize the buffer - len = vsnprintf(NULL, 0, format, vararg); - asciiMessageBuffer.resize(len + 1); - - // Print again - vsnprintf(&asciiMessageBuffer[0], asciiMessageBuffer.size(), format, vararg); - } - - // NULL terminate the buffer to be safe - asciiMessageBuffer[len] = '\0'; + std::string formattedMessage = FormatString(format, vararg); #endif #if defined(ANGLE_ENABLE_PERF) @@ -48,12 +34,12 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c { // The perf function only accepts wide strings, widen the ascii message static std::wstring wideMessage; - if (wideMessage.capacity() < asciiMessageBuffer.size()) + if (wideMessage.capacity() < formattedMessage.length()) { - wideMessage.reserve(asciiMessageBuffer.size()); + wideMessage.reserve(formattedMessage.size()); } - wideMessage.assign(asciiMessageBuffer.begin(), asciiMessageBuffer.begin() + len); + wideMessage.assign(formattedMessage.begin(), formattedMessage.end()); perfFunc(0, wideMessage.c_str()); } @@ -70,7 +56,7 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app); if (file) { - file.write(&asciiMessageBuffer[0], len); + file.write(formattedMessage.c_str(), formattedMessage.length()); file.flush(); } diff --git a/src/3rdparty/angle/src/common/debug.h b/src/3rdparty/angle/src/common/debug.h index 997ebca6be..bf2bca8f24 100644 --- a/src/3rdparty/angle/src/common/debug.h +++ b/src/3rdparty/angle/src/common/debug.h @@ -91,6 +91,10 @@ namespace gl // A macro to indicate unimplemented functionality +#if defined (ANGLE_TEST_CONFIG) +#define NOASSERT_UNIMPLEMENTED 1 +#endif + // Define NOASSERT_UNIMPLEMENTED to non zero to skip the assert fail in the unimplemented checks // This will allow us to test with some automated test suites (eg dEQP) without crashing #ifndef NOASSERT_UNIMPLEMENTED diff --git a/src/3rdparty/angle/src/common/event_tracer.cpp b/src/3rdparty/angle/src/common/event_tracer.cpp deleted file mode 100644 index 353c69d05c..0000000000 --- a/src/3rdparty/angle/src/common/event_tracer.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "common/event_tracer.h" - -namespace gl -{ - -GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag; -AddTraceEventFunc g_addTraceEvent; - -} // namespace gl - -extern "C" { - -void TRACE_ENTRY SetTraceFunctionPointers(GetCategoryEnabledFlagFunc getCategoryEnabledFlag, - AddTraceEventFunc addTraceEvent) -{ - gl::g_getCategoryEnabledFlag = getCategoryEnabledFlag; - gl::g_addTraceEvent = addTraceEvent; -} - -} // extern "C" - -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 deleted file mode 100644 index fa97435faa..0000000000 --- a/src/3rdparty/angle/src/common/event_tracer.h +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMMON_EVENT_TRACER_H_ -#define COMMON_EVENT_TRACER_H_ - -#include "common/platform.h" - -#if !defined(TRACE_ENTRY) -# ifdef ANGLE_PLATFORM_WINDOWS -# define TRACE_ENTRY __stdcall -# else -# define TRACE_ENTRY -# endif // ANGLE_PLATFORM_WINDOWS -#endif //TRACE_ENTRY - -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); - -// extern "C" so that it has a reasonable name for GetProcAddress. -void TRACE_ENTRY SetTraceFunctionPointers(GetCategoryEnabledFlagFunc get_category_enabled_flag, - AddTraceEventFunc add_trace_event_func); - -} - -namespace gl -{ - -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/mathutil.cpp b/src/3rdparty/angle/src/common/mathutil.cpp index 20b3f0c113..496633632b 100644 --- a/src/3rdparty/angle/src/common/mathutil.cpp +++ b/src/3rdparty/angle/src/common/mathutil.cpp @@ -7,6 +7,7 @@ // mathutil.cpp: Math and bit manipulation functions. #include "common/mathutil.h" + #include #include diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h index f32663fa02..52f2bc1c0e 100644 --- a/src/3rdparty/angle/src/common/mathutil.h +++ b/src/3rdparty/angle/src/common/mathutil.h @@ -505,21 +505,33 @@ inline unsigned int averageFloat10(unsigned int a, unsigned int b) namespace rx { +template struct Range { Range() {} - Range(int lo, int hi) : start(lo), end(hi) { ASSERT(lo <= hi); } + Range(T lo, T hi) : start(lo), end(hi) { ASSERT(lo <= hi); } + + T start; + T end; - int start; - int end; + T length() const { return end - start; } }; +typedef Range RangeI; +typedef Range RangeUI; + template T roundUp(const T value, const T alignment) { return value + alignment - 1 - (value - 1) % alignment; } +inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor) +{ + unsigned int divided = value / divisor; + return (divided + ((value % divisor == 0) ? 0 : 1)); +} + template inline bool IsUnsignedAdditionSafe(T lhs, T rhs) { diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h index 44c5c7c03b..b53394f337 100644 --- a/src/3rdparty/angle/src/common/platform.h +++ b/src/3rdparty/angle/src/common/platform.h @@ -52,6 +52,9 @@ # if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_PERF) # include +# if !defined(COMPILER_IMPLEMENTATION) +# include +# endif # endif # if defined(ANGLE_ENABLE_D3D11) @@ -61,16 +64,25 @@ # include # if _MSC_VER >= 1700 # include +# endif +# if !defined(COMPILER_IMPLEMENTATION) # include # endif +# if defined(__MINGW32__) +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; +# endif # endif # undef near # undef far -# undef NEAR -# define NEAR -# undef FAR -# define FAR #endif #endif // COMMON_PLATFORM_H_ diff --git a/src/3rdparty/angle/src/common/shadervars.h b/src/3rdparty/angle/src/common/shadervars.h deleted file mode 100644 index 0442d81500..0000000000 --- a/src/3rdparty/angle/src/common/shadervars.h +++ /dev/null @@ -1,157 +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. -// -// shadervars.h: -// Types to represent GL variables (varyings, uniforms, etc) -// - -#ifndef COMMON_SHADERVARIABLE_H_ -#define COMMON_SHADERVARIABLE_H_ - -#include -#include -#include -#include "GLSLANG/ShaderLang.h" - -namespace sh -{ - -// Varying interpolation qualifier, see section 4.3.9 of the ESSL 3.00.4 spec -enum InterpolationType -{ - INTERPOLATION_SMOOTH, - INTERPOLATION_CENTROID, - INTERPOLATION_FLAT -}; - -// Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec -enum BlockLayoutType -{ - BLOCKLAYOUT_STANDARD, - BLOCKLAYOUT_PACKED, - BLOCKLAYOUT_SHARED -}; - -// Base class for all variables defined in shaders, including Varyings, Uniforms, etc -struct ShaderVariable -{ - ShaderVariable() - : type(0), - precision(0), - arraySize(0), - staticUse(false) - {} - - ShaderVariable(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn) - : type(typeIn), - precision(precisionIn), - name(nameIn), - arraySize(arraySizeIn), - staticUse(false) - {} - - bool isArray() const { return arraySize > 0; } - unsigned int elementCount() const { return std::max(1u, arraySize); } - - GLenum type; - GLenum precision; - std::string name; - std::string mappedName; - unsigned int arraySize; - bool staticUse; -}; - -struct Uniform : public ShaderVariable -{ - Uniform() - {} - - Uniform(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn) - : ShaderVariable(typeIn, precisionIn, nameIn, arraySizeIn) - {} - - bool isStruct() const { return !fields.empty(); } - - std::vector fields; -}; - -struct Attribute : public ShaderVariable -{ - Attribute() - : location(-1) - {} - - Attribute(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, int locationIn) - : ShaderVariable(typeIn, precisionIn, nameIn, arraySizeIn), - location(locationIn) - {} - - int location; -}; - -struct InterfaceBlockField : public ShaderVariable -{ - InterfaceBlockField() - : isRowMajorMatrix(false) - {} - - InterfaceBlockField(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, bool isRowMajorMatrix) - : ShaderVariable(typeIn, precisionIn, nameIn, arraySizeIn), - isRowMajorMatrix(isRowMajorMatrix) - {} - - bool isStruct() const { return !fields.empty(); } - - bool isRowMajorMatrix; - std::vector fields; -}; - -struct Varying : public ShaderVariable -{ - Varying() - : interpolation(INTERPOLATION_SMOOTH) - {} - - Varying(GLenum typeIn, GLenum precisionIn, const char *nameIn, unsigned int arraySizeIn, InterpolationType interpolationIn) - : ShaderVariable(typeIn, precisionIn, nameIn, arraySizeIn), - interpolation(interpolationIn) - {} - - bool isStruct() const { return !fields.empty(); } - - InterpolationType interpolation; - std::vector fields; - std::string structName; -}; - -struct InterfaceBlock -{ - InterfaceBlock() - : arraySize(0), - layout(BLOCKLAYOUT_PACKED), - isRowMajorLayout(false), - staticUse(false) - {} - - InterfaceBlock(const char *name, unsigned int arraySize) - : name(name), - arraySize(arraySize), - layout(BLOCKLAYOUT_SHARED), - isRowMajorLayout(false), - staticUse(false) - {} - - std::string name; - std::string mappedName; - unsigned int arraySize; - BlockLayoutType layout; - bool isRowMajorLayout; - bool staticUse; - std::vector fields; -}; - -} - -#endif // COMMON_SHADERVARIABLE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h index ba9ef5e609..324b0669f4 100644 --- a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h +++ b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h @@ -69,40 +69,9 @@ enum TBasicType EbtStruct, EbtInterfaceBlock, EbtAddress, // should be deprecated?? - EbtInvariant // used as a type when qualifying a previously declared variable as being invariant }; -inline const char* getBasicString(TBasicType t) -{ - switch (t) - { - case EbtVoid: return "void"; break; - case EbtFloat: return "float"; break; - case EbtInt: return "int"; break; - case EbtUInt: return "uint"; break; - case EbtBool: return "bool"; break; - case EbtSampler2D: return "sampler2D"; break; - case EbtSampler3D: return "sampler3D"; break; - case EbtSamplerCube: return "samplerCube"; break; - case EbtSamplerExternalOES: return "samplerExternalOES"; break; - case EbtSampler2DRect: return "sampler2DRect"; break; - case EbtSampler2DArray: return "sampler2DArray"; break; - case EbtISampler2D: return "isampler2D"; break; - case EbtISampler3D: return "isampler3D"; break; - case EbtISamplerCube: return "isamplerCube"; break; - case EbtISampler2DArray: return "isampler2DArray"; break; - case EbtUSampler2D: return "usampler2D"; break; - case EbtUSampler3D: return "usampler3D"; break; - case EbtUSamplerCube: return "usamplerCube"; break; - case EbtUSampler2DArray: return "usampler2DArray"; break; - case EbtSampler2DShadow: return "sampler2DShadow"; break; - case EbtSamplerCubeShadow: return "samplerCubeShadow"; break; - case EbtSampler2DArrayShadow: return "sampler2DArrayShadow"; break; - case EbtStruct: return "structure"; break; - case EbtInterfaceBlock: return "interface block"; break; - default: return "unknown type"; - } -} +const char* getBasicString(TBasicType t); inline bool IsSampler(TBasicType type) { diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h index 926b6bed69..c6bf77c386 100644 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h @@ -8,7 +8,7 @@ #define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ #include "compiler/translator/InfoSink.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // // This class decides which built-in functions need to be replaced with the diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp index 0606c72e39..368cd2ae4a 100644 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp @@ -12,6 +12,7 @@ #include "compiler/translator/InitializeParseContext.h" #include "compiler/translator/InitializeVariables.h" #include "compiler/translator/ParseContext.h" +#include "compiler/translator/RegenerateStructNames.h" #include "compiler/translator/RenameFunction.h" #include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h" #include "compiler/translator/UnfoldShortCircuitAST.h" @@ -257,10 +258,17 @@ bool TCompiler::compile(const char* const shaderStrings[], if (success && (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)) { - ScalarizeVecAndMatConstructorArgs scalarizer; + ScalarizeVecAndMatConstructorArgs scalarizer( + shaderType, fragmentPrecisionHigh); root->traverse(&scalarizer); } + if (success && (compileOptions & SH_REGENERATE_STRUCT_NAMES)) + { + RegenerateStructNames gen(symbolTable, shaderVersion); + root->traverse(&gen); + } + if (success && (compileOptions & SH_INTERMEDIATE_TREE)) intermediate.outputTree(root); @@ -494,18 +502,18 @@ bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root) void TCompiler::collectVariables(TIntermNode* root) { - CollectVariables collect(&attributes, - &outputVariables, - &uniforms, - &varyings, - &interfaceBlocks, - hashFunction); + sh::CollectVariables collect(&attributes, + &outputVariables, + &uniforms, + &varyings, + &interfaceBlocks, + hashFunction); root->traverse(&collect); // For backwards compatiblity with ShGetVariableInfo, expand struct // uniforms and varyings into separate variables for each field. - ExpandVariables(uniforms, &expandedUniforms); - ExpandVariables(varyings, &expandedVaryings); + sh::ExpandVariables(uniforms, &expandedUniforms); + sh::ExpandVariables(varyings, &expandedVaryings); } bool TCompiler::enforcePackingRestrictions() diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.h b/src/3rdparty/angle/src/compiler/translator/Compiler.h index 5eac2d89d1..ca0c157884 100644 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.h +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.h @@ -71,9 +71,9 @@ class TCompiler : public TShHandleBase const std::vector &getAttributes() const { return attributes; } const std::vector &getOutputVariables() const { return outputVariables; } const std::vector &getUniforms() const { return uniforms; } - const std::vector &getExpandedUniforms() const { return expandedUniforms; } + const std::vector &getExpandedUniforms() const { return expandedUniforms; } const std::vector &getVaryings() const { return varyings; } - const std::vector &getExpandedVaryings() const { return expandedVaryings; } + const std::vector &getExpandedVaryings() const { return expandedVaryings; } const std::vector &getInterfaceBlocks() const { return interfaceBlocks; } ShHashFunction64 getHashFunction() const { return hashFunction; } @@ -83,6 +83,9 @@ class TCompiler : public TShHandleBase ShShaderOutput getOutputType() const { return outputType; } std::string getBuiltInResourcesString() const { return builtInResourcesString; } + // Get the resources set by InitBuiltInSymbolTable + const ShBuiltInResources& getResources() const; + protected: sh::GLenum getShaderType() const { return shaderType; } // Initialize symbol-table with built-in symbols. @@ -128,8 +131,6 @@ class TCompiler : public TShHandleBase bool limitExpressionComplexity(TIntermNode* root); // Get built-in extensions with default behavior. const TExtensionBehavior& getExtensionBehavior() const; - // Get the resources set by InitBuiltInSymbolTable - const ShBuiltInResources& getResources() const; const ArrayBoundsClamper& getArrayBoundsClamper() const; ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const; @@ -138,9 +139,9 @@ class TCompiler : public TShHandleBase std::vector attributes; std::vector outputVariables; std::vector uniforms; - std::vector expandedUniforms; + std::vector expandedUniforms; std::vector varyings; - std::vector expandedVaryings; + std::vector expandedVaryings; std::vector interfaceBlocks; private: diff --git a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h index cb76f1de02..86810650dc 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h +++ b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h @@ -8,7 +8,7 @@ #define COMPILER_DETECT_RECURSION_H_ #include -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/VariableInfo.h" class TInfoSink; diff --git a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h index 1dd8be9233..35d66cbc2e 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h +++ b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h @@ -11,7 +11,7 @@ #ifndef COMPILER_DETECTDISCONTINUITY_H_ #define COMPILER_DETECTDISCONTINUITY_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h index 610205eb92..c93a6f808e 100644 --- a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h +++ b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h @@ -7,7 +7,7 @@ #ifndef COMPILER_FLAGSTD140STRUCTS_H_ #define COMPILER_FLAGSTD140STRUCTS_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/translator/HashNames.h b/src/3rdparty/angle/src/compiler/translator/HashNames.h index 85161428b2..26546a3e7b 100644 --- a/src/3rdparty/angle/src/compiler/translator/HashNames.h +++ b/src/3rdparty/angle/src/compiler/translator/HashNames.h @@ -9,7 +9,7 @@ #include -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #define HASHED_NAME_PREFIX "webgl_" diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp index e91d64f43b..10b21e6d28 100644 --- a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp @@ -12,7 +12,7 @@ #include "compiler/translator/Initialize.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "angle_gl.h" void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable) diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h index 81ab9fe90f..59c3ea0a39 100644 --- a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h +++ b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h @@ -7,7 +7,7 @@ #ifndef COMPILER_INITIALIZE_VARIABLES_H_ #define COMPILER_INITIALIZE_VARIABLES_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class InitializeVariables : public TIntermTraverser { diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp new file mode 100644 index 0000000000..b155545ad2 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp @@ -0,0 +1,1107 @@ +// +// 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. +// + +// +// Build the intermediate representation. +// + +#include +#include +#include + +#include "compiler/translator/HashNames.h" +#include "compiler/translator/IntermNode.h" +#include "compiler/translator/SymbolTable.h" + +namespace +{ + +TPrecision GetHigherPrecision(TPrecision left, TPrecision right) +{ + return left > right ? left : right; +} + +bool ValidateMultiplication(TOperator op, const TType &left, const TType &right) +{ + switch (op) + { + case EOpMul: + case EOpMulAssign: + return left.getNominalSize() == right.getNominalSize() && + left.getSecondarySize() == right.getSecondarySize(); + case EOpVectorTimesScalar: + case EOpVectorTimesScalarAssign: + return true; + case EOpVectorTimesMatrix: + return left.getNominalSize() == right.getRows(); + case EOpVectorTimesMatrixAssign: + return left.getNominalSize() == right.getRows() && + left.getNominalSize() == right.getCols(); + case EOpMatrixTimesVector: + return left.getCols() == right.getNominalSize(); + case EOpMatrixTimesScalar: + case EOpMatrixTimesScalarAssign: + return true; + case EOpMatrixTimesMatrix: + return left.getCols() == right.getRows(); + case EOpMatrixTimesMatrixAssign: + return left.getCols() == right.getCols() && + left.getRows() == right.getRows(); + + default: + UNREACHABLE(); + return false; + } +} + +bool CompareStructure(const TType& leftNodeType, + ConstantUnion *rightUnionArray, + ConstantUnion *leftUnionArray); + +bool CompareStruct(const TType &leftNodeType, + ConstantUnion *rightUnionArray, + ConstantUnion *leftUnionArray) +{ + const TFieldList &fields = leftNodeType.getStruct()->fields(); + + size_t structSize = fields.size(); + size_t index = 0; + + for (size_t j = 0; j < structSize; j++) + { + size_t size = fields[j]->type()->getObjectSize(); + for (size_t i = 0; i < size; i++) + { + if (fields[j]->type()->getBasicType() == EbtStruct) + { + if (!CompareStructure(*fields[j]->type(), + &rightUnionArray[index], + &leftUnionArray[index])) + { + return false; + } + } + else + { + if (leftUnionArray[index] != rightUnionArray[index]) + return false; + index++; + } + } + } + return true; +} + +bool CompareStructure(const TType &leftNodeType, + ConstantUnion *rightUnionArray, + ConstantUnion *leftUnionArray) +{ + if (leftNodeType.isArray()) + { + TType typeWithoutArrayness = leftNodeType; + typeWithoutArrayness.clearArrayness(); + + size_t arraySize = leftNodeType.getArraySize(); + + for (size_t i = 0; i < arraySize; ++i) + { + size_t offset = typeWithoutArrayness.getObjectSize() * i; + if (!CompareStruct(typeWithoutArrayness, + &rightUnionArray[offset], + &leftUnionArray[offset])) + { + return false; + } + } + } + else + { + return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); + } + return true; +} + +} // namespace anonymous + + +//////////////////////////////////////////////////////////////// +// +// Member functions of the nodes used for building the tree. +// +//////////////////////////////////////////////////////////////// + +#define REPLACE_IF_IS(node, type, original, replacement) \ + if (node == original) { \ + node = static_cast(replacement); \ + return true; \ + } + +bool TIntermLoop::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mInit, TIntermNode, original, replacement); + REPLACE_IF_IS(mCond, TIntermTyped, original, replacement); + REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement); + REPLACE_IF_IS(mBody, TIntermNode, original, replacement); + 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) +{ + REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement); + return false; +} + +void TIntermBranch::enqueueChildren(std::queue *nodeQueue) const +{ + if (mExpression) + { + nodeQueue->push(mExpression); + } +} + +bool TIntermBinary::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement); + REPLACE_IF_IS(mRight, TIntermTyped, original, replacement); + 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) +{ + REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); + return false; +} + +void TIntermUnary::enqueueChildren(std::queue *nodeQueue) const +{ + if (mOperand) + { + nodeQueue->push(mOperand); + } +} + +bool TIntermAggregate::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + for (size_t ii = 0; ii < mSequence.size(); ++ii) + { + REPLACE_IF_IS(mSequence[ii], TIntermNode, original, replacement); + } + return false; +} + +void TIntermAggregate::enqueueChildren(std::queue *nodeQueue) const +{ + for (size_t childIndex = 0; childIndex < mSequence.size(); childIndex++) + { + nodeQueue->push(mSequence[childIndex]); + } +} + +bool TIntermSelection::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); + REPLACE_IF_IS(mTrueBlock, TIntermNode, original, replacement); + REPLACE_IF_IS(mFalseBlock, TIntermNode, original, replacement); + return false; +} + +void TIntermSelection::enqueueChildren(std::queue *nodeQueue) const +{ + if (mCondition) + { + nodeQueue->push(mCondition); + } + if (mTrueBlock) + { + nodeQueue->push(mTrueBlock); + } + if (mFalseBlock) + { + nodeQueue->push(mFalseBlock); + } +} + +// +// Say whether or not an operation node changes the value of a variable. +// +bool TIntermOperator::isAssignment() const +{ + switch (mOp) + { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + case EOpAssign: + case EOpAddAssign: + case EOpSubAssign: + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + case EOpDivAssign: + return true; + default: + return false; + } +} + +// +// returns true if the operator is for one of the constructors +// +bool TIntermOperator::isConstructor() const +{ + switch (mOp) + { + case EOpConstructVec2: + case EOpConstructVec3: + case EOpConstructVec4: + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: + case EOpConstructFloat: + case EOpConstructIVec2: + case EOpConstructIVec3: + case EOpConstructIVec4: + case EOpConstructInt: + case EOpConstructUVec2: + case EOpConstructUVec3: + case EOpConstructUVec4: + case EOpConstructUInt: + case EOpConstructBVec2: + case EOpConstructBVec3: + case EOpConstructBVec4: + case EOpConstructBool: + case EOpConstructStruct: + return true; + default: + return false; + } +} + +// +// Make sure the type of a unary operator is appropriate for its +// combination of operation and operand type. +// +// Returns false in nothing makes sense. +// +bool TIntermUnary::promote(TInfoSink &) +{ + switch (mOp) + { + case EOpLogicalNot: + if (mOperand->getBasicType() != EbtBool) + return false; + break; + case EOpNegative: + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + if (mOperand->getBasicType() == EbtBool) + return false; + break; + + // operators for built-ins are already type checked against their prototype + case EOpAny: + case EOpAll: + case EOpVectorLogicalNot: + return true; + + default: + if (mOperand->getBasicType() != EbtFloat) + return false; + } + + setType(mOperand->getType()); + mType.setQualifier(EvqTemporary); + + return true; +} + +// +// Establishes the type of the resultant operation, as well as +// makes the operator the correct one for the operands. +// +// Returns false if operator can't work on operands. +// +bool TIntermBinary::promote(TInfoSink &infoSink) +{ + // This function only handles scalars, vectors, and matrices. + if (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; + } + + // + // Base assumption: just make the type the same as the left + // operand. Then only deviations from this need be coded. + // + setType(mLeft->getType()); + + // The result gets promoted to the highest precision. + TPrecision higherPrecision = GetHigherPrecision( + mLeft->getPrecision(), mRight->getPrecision()); + getTypePointer()->setPrecision(higherPrecision); + + // Binary operations results in temporary variables unless both + // operands are const. + if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst) + { + getTypePointer()->setQualifier(EvqTemporary); + } + + const int nominalSize = + std::max(mLeft->getNominalSize(), mRight->getNominalSize()); + + // + // All scalars or structs. Code after this test assumes this case is removed! + // + if (nominalSize == 1) + { + switch (mOp) + { + // + // Promote to conditional + // + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + setType(TType(EbtBool, EbpUndefined)); + break; + + // + // And and Or operate on conditionals + // + case EOpLogicalAnd: + case EOpLogicalOr: + // Both operands must be of type bool. + if (mLeft->getBasicType() != EbtBool || mRight->getBasicType() != EbtBool) + { + return false; + } + setType(TType(EbtBool, EbpUndefined)); + break; + + default: + break; + } + return true; + } + + // If we reach here, at least one of the operands is vector or matrix. + // The other operand could be a scalar, vector, or matrix. + // Can these two operands be combined? + // + TBasicType basicType = mLeft->getBasicType(); + switch (mOp) + { + case EOpMul: + if (!mLeft->isMatrix() && mRight->isMatrix()) + { + if (mLeft->isVector()) + { + mOp = EOpVectorTimesMatrix; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), 1)); + } + else + { + mOp = EOpMatrixTimesScalar; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), mRight->getRows())); + } + } + else if (mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mRight->isVector()) + { + mOp = EOpMatrixTimesVector; + setType(TType(basicType, higherPrecision, EvqTemporary, + mLeft->getRows(), 1)); + } + else + { + mOp = EOpMatrixTimesScalar; + } + } + else if (mLeft->isMatrix() && mRight->isMatrix()) + { + mOp = EOpMatrixTimesMatrix; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), mLeft->getRows())); + } + else if (!mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mLeft->isVector() && mRight->isVector()) + { + // leave as component product + } + else if (mLeft->isVector() || mRight->isVector()) + { + mOp = EOpVectorTimesScalar; + setType(TType(basicType, higherPrecision, EvqTemporary, + nominalSize, 1)); + } + } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), + "Missing elses"); + return false; + } + + if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType())) + { + return false; + } + break; + + case EOpMulAssign: + if (!mLeft->isMatrix() && mRight->isMatrix()) + { + if (mLeft->isVector()) + { + mOp = EOpVectorTimesMatrixAssign; + } + else + { + return false; + } + } + else if (mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mRight->isVector()) + { + return false; + } + else + { + mOp = EOpMatrixTimesScalarAssign; + } + } + else if (mLeft->isMatrix() && mRight->isMatrix()) + { + mOp = EOpMatrixTimesMatrixAssign; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), mLeft->getRows())); + } + else if (!mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mLeft->isVector() && mRight->isVector()) + { + // leave as component product + } + else if (mLeft->isVector() || mRight->isVector()) + { + if (!mLeft->isVector()) + return false; + mOp = EOpVectorTimesScalarAssign; + setType(TType(basicType, higherPrecision, EvqTemporary, + mLeft->getNominalSize(), 1)); + } + } + else + { + infoSink.info.message(EPrefixInternalError, getLine(), + "Missing elses"); + return false; + } + + if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType())) + { + return false; + } + break; + + case EOpAssign: + case EOpInitialize: + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpAddAssign: + case EOpSubAssign: + case EOpDivAssign: + if ((mLeft->isMatrix() && mRight->isVector()) || + (mLeft->isVector() && mRight->isMatrix())) + { + return false; + } + + // Are the sizes compatible? + 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 (!mLeft->isScalar() && !mRight->isScalar()) + return false; + + // Operator cannot be of type pure assignment. + if (mOp == EOpAssign || mOp == EOpInitialize) + return false; + } + + { + const int secondarySize = std::max( + mLeft->getSecondarySize(), mRight->getSecondarySize()); + setType(TType(basicType, higherPrecision, EvqTemporary, + nominalSize, secondarySize)); + } + break; + + case EOpEqual: + case EOpNotEqual: + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if ((mLeft->getNominalSize() != mRight->getNominalSize()) || + (mLeft->getSecondarySize() != mRight->getSecondarySize())) + { + return false; + } + setType(TType(EbtBool, EbpUndefined)); + break; + + default: + return false; + } + return true; +} + +// +// The fold functions see if an operation on a constant can be done in place, +// without generating run-time code. +// +// Returns the node to keep using, which may or may not be the node passed in. +// +TIntermTyped *TIntermConstantUnion::fold( + TOperator op, TIntermTyped *constantNode, TInfoSink &infoSink) +{ + ConstantUnion *unionArray = getUnionArrayPointer(); + + if (!unionArray) + return NULL; + + size_t objectSize = getType().getObjectSize(); + + if (constantNode) + { + // binary operations + TIntermConstantUnion *node = constantNode->getAsConstantUnion(); + ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); + TType returnType = getType(); + + if (!rightUnionArray) + return NULL; + + // for a case like float f = 1.2 + vec4(2,3,4,5); + if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) + { + rightUnionArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; ++i) + { + rightUnionArray[i] = *node->getUnionArrayPointer(); + } + returnType = getType(); + } + else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) + { + // for a case like float f = vec4(2,3,4,5) + 1.2; + unionArray = new ConstantUnion[constantNode->getType().getObjectSize()]; + for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) + { + unionArray[i] = *getUnionArrayPointer(); + } + returnType = node->getType(); + objectSize = constantNode->getType().getObjectSize(); + } + + ConstantUnion *tempConstArray = NULL; + TIntermConstantUnion *tempNode; + + bool boolNodeFlag = false; + switch(op) + { + case EOpAdd: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] + rightUnionArray[i]; + break; + case EOpSub: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] - rightUnionArray[i]; + break; + + case EOpMul: + case EOpVectorTimesScalar: + case EOpMatrixTimesScalar: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] * rightUnionArray[i]; + break; + + case EOpMatrixTimesMatrix: + { + if (getType().getBasicType() != EbtFloat || + node->getBasicType() != EbtFloat) + { + infoSink.info.message( + EPrefixInternalError, getLine(), + "Constant Folding cannot be done for matrix multiply"); + return NULL; + } + + const int leftCols = getCols(); + const int leftRows = getRows(); + const int rightCols = constantNode->getType().getCols(); + const int rightRows = constantNode->getType().getRows(); + const int resultCols = rightCols; + const int resultRows = leftRows; + + tempConstArray = new ConstantUnion[resultCols*resultRows]; + for (int row = 0; row < resultRows; row++) + { + for (int column = 0; column < resultCols; column++) + { + tempConstArray[resultRows * column + row].setFConst(0.0f); + for (int i = 0; i < leftCols; i++) + { + tempConstArray[resultRows * column + row].setFConst( + tempConstArray[resultRows * column + row].getFConst() + + unionArray[i * leftRows + row].getFConst() * + rightUnionArray[column * rightRows + i].getFConst()); + } + } + } + + // update return type for matrix product + returnType.setPrimarySize(resultCols); + returnType.setSecondarySize(resultRows); + } + break; + + case EOpDiv: + { + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + switch (getType().getBasicType()) + { + case EbtFloat: + if (rightUnionArray[i] == 0.0f) + { + infoSink.info.message( + EPrefixWarning, getLine(), + "Divide by zero error during constant folding"); + tempConstArray[i].setFConst( + unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX); + } + else + { + tempConstArray[i].setFConst( + unionArray[i].getFConst() / + rightUnionArray[i].getFConst()); + } + break; + + case EbtInt: + if (rightUnionArray[i] == 0) + { + infoSink.info.message( + EPrefixWarning, getLine(), + "Divide by zero error during constant folding"); + tempConstArray[i].setIConst(INT_MAX); + } + else + { + tempConstArray[i].setIConst( + unionArray[i].getIConst() / + rightUnionArray[i].getIConst()); + } + break; + + case EbtUInt: + if (rightUnionArray[i] == 0) + { + infoSink.info.message( + EPrefixWarning, getLine(), + "Divide by zero error during constant folding"); + tempConstArray[i].setUConst(UINT_MAX); + } + else + { + tempConstArray[i].setUConst( + unionArray[i].getUConst() / + rightUnionArray[i].getUConst()); + } + break; + + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Constant folding cannot be done for \"/\""); + return NULL; + } + } + } + break; + + case EOpMatrixTimesVector: + { + if (node->getBasicType() != EbtFloat) + { + infoSink.info.message( + EPrefixInternalError, getLine(), + "Constant Folding cannot be done for matrix times vector"); + return NULL; + } + + const int matrixCols = getCols(); + const int matrixRows = getRows(); + + tempConstArray = new ConstantUnion[matrixRows]; + + for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) + { + tempConstArray[matrixRow].setFConst(0.0f); + for (int col = 0; col < matrixCols; col++) + { + tempConstArray[matrixRow].setFConst( + tempConstArray[matrixRow].getFConst() + + unionArray[col * matrixRows + matrixRow].getFConst() * + rightUnionArray[col].getFConst()); + } + } + + returnType = node->getType(); + returnType.setPrimarySize(matrixRows); + + tempNode = new TIntermConstantUnion(tempConstArray, returnType); + tempNode->setLine(getLine()); + + return tempNode; + } + + case EOpVectorTimesMatrix: + { + if (getType().getBasicType() != EbtFloat) + { + infoSink.info.message( + EPrefixInternalError, getLine(), + "Constant Folding cannot be done for vector times matrix"); + return NULL; + } + + const int matrixCols = constantNode->getType().getCols(); + const int matrixRows = constantNode->getType().getRows(); + + tempConstArray = new ConstantUnion[matrixCols]; + + for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++) + { + tempConstArray[matrixCol].setFConst(0.0f); + for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) + { + tempConstArray[matrixCol].setFConst( + tempConstArray[matrixCol].getFConst() + + unionArray[matrixRow].getFConst() * + rightUnionArray[matrixCol * matrixRows + matrixRow].getFConst()); + } + } + + returnType.setPrimarySize(matrixCols); + } + break; + + case EOpLogicalAnd: + // this code is written for possible future use, + // will not get executed currently + { + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + tempConstArray[i] = unionArray[i] && rightUnionArray[i]; + } + } + break; + + case EOpLogicalOr: + // this code is written for possible future use, + // will not get executed currently + { + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + tempConstArray[i] = unionArray[i] || rightUnionArray[i]; + } + } + break; + + case EOpLogicalXor: + { + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + switch (getType().getBasicType()) + { + case EbtBool: + tempConstArray[i].setBConst( + unionArray[i] == rightUnionArray[i] ? false : true); + break; + default: + UNREACHABLE(); + break; + } + } + } + break; + + case EOpLessThan: + ASSERT(objectSize == 1); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(*unionArray < *rightUnionArray); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + + case EOpGreaterThan: + ASSERT(objectSize == 1); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(*unionArray > *rightUnionArray); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + + case EOpLessThanEqual: + { + ASSERT(objectSize == 1); + ConstantUnion constant; + constant.setBConst(*unionArray > *rightUnionArray); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(!constant.getBConst()); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + } + + case EOpGreaterThanEqual: + { + ASSERT(objectSize == 1); + ConstantUnion constant; + constant.setBConst(*unionArray < *rightUnionArray); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(!constant.getBConst()); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; + } + + case EOpEqual: + if (getType().getBasicType() == EbtStruct) + { + if (!CompareStructure(node->getType(), + node->getUnionArrayPointer(), + unionArray)) + { + boolNodeFlag = true; + } + } + else + { + for (size_t i = 0; i < objectSize; i++) + { + if (unionArray[i] != rightUnionArray[i]) + { + boolNodeFlag = true; + break; // break out of for loop + } + } + } + + tempConstArray = new ConstantUnion[1]; + if (!boolNodeFlag) + { + tempConstArray->setBConst(true); + } + else + { + tempConstArray->setBConst(false); + } + + tempNode = new TIntermConstantUnion( + tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); + tempNode->setLine(getLine()); + + return tempNode; + + case EOpNotEqual: + if (getType().getBasicType() == EbtStruct) + { + if (CompareStructure(node->getType(), + node->getUnionArrayPointer(), + unionArray)) + { + boolNodeFlag = true; + } + } + else + { + for (size_t i = 0; i < objectSize; i++) + { + if (unionArray[i] == rightUnionArray[i]) + { + boolNodeFlag = true; + break; // break out of for loop + } + } + } + + tempConstArray = new ConstantUnion[1]; + if (!boolNodeFlag) + { + tempConstArray->setBConst(true); + } + else + { + tempConstArray->setBConst(false); + } + + tempNode = new TIntermConstantUnion( + tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); + tempNode->setLine(getLine()); + + return tempNode; + + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Invalid operator for constant folding"); + return NULL; + } + tempNode = new TIntermConstantUnion(tempConstArray, returnType); + tempNode->setLine(getLine()); + + return tempNode; + } + else + { + // + // Do unary operations + // + TIntermConstantUnion *newNode = 0; + ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + { + switch(op) + { + case EOpNegative: + switch (getType().getBasicType()) + { + case EbtFloat: + tempConstArray[i].setFConst(-unionArray[i].getFConst()); + break; + case EbtInt: + tempConstArray[i].setIConst(-unionArray[i].getIConst()); + break; + case EbtUInt: + tempConstArray[i].setUConst(static_cast( + -static_cast(unionArray[i].getUConst()))); + break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return NULL; + } + break; + + case EOpLogicalNot: + // this code is written for possible future use, + // will not get executed currently + switch (getType().getBasicType()) + { + case EbtBool: + tempConstArray[i].setBConst(!unionArray[i].getBConst()); + break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return NULL; + } + break; + + default: + return NULL; + } + } + newNode = new TIntermConstantUnion(tempConstArray, getType()); + newNode->setLine(getLine()); + return newNode; + } +} + +// static +TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction) +{ + if (hashFunction == NULL || name.empty()) + return name; + khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length()); + TStringStream stream; + stream << HASHED_NAME_PREFIX << std::hex << number; + TString hashedName = stream.str(); + return hashedName; +} diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.h b/src/3rdparty/angle/src/compiler/translator/IntermNode.h new file mode 100644 index 0000000000..ec440da010 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.h @@ -0,0 +1,772 @@ +// +// 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. +// + +// +// Definition of the in-memory high-level intermediate representation +// of shaders. This is a tree that parser creates. +// +// Nodes in the tree are defined as a hierarchy of classes derived from +// TIntermNode. Each is a node in a tree. There is no preset branching factor; +// each node can have it's own type of list of children. +// + +#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_ +#define COMPILER_TRANSLATOR_INTERMEDIATE_H_ + +#include "GLSLANG/ShaderLang.h" + +#include +#include + +#include "compiler/translator/Common.h" +#include "compiler/translator/Types.h" +#include "compiler/translator/ConstantUnion.h" + +// +// Operators used by the high-level (parse tree) representation. +// +enum TOperator +{ + EOpNull, // if in a node, should only mean a node is still being built + EOpSequence, // denotes a list of statements, or parameters, etc. + EOpFunctionCall, + EOpFunction, // For function definition + EOpParameters, // an aggregate listing the parameters to a function + + EOpDeclaration, + EOpInvariantDeclaration, // Specialized declarations for attributing invariance + EOpPrototype, + + // + // Unary operators + // + + EOpNegative, + 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 +}; + +class TIntermTraverser; +class TIntermAggregate; +class TIntermBinary; +class TIntermUnary; +class TIntermConstantUnion; +class TIntermSelection; +class TIntermTyped; +class TIntermSymbol; +class TIntermLoop; +class TInfoSink; +class TIntermRaw; + +// +// Base class for the tree nodes +// +class TIntermNode +{ + public: + POOL_ALLOCATOR_NEW_DELETE(); + TIntermNode() + { + // TODO: Move this to TSourceLoc constructor + // after getting rid of TPublicType. + mLine.first_file = mLine.last_file = 0; + mLine.first_line = mLine.last_line = 0; + } + virtual ~TIntermNode() { } + + const TSourceLoc &getLine() const { return mLine; } + void setLine(const TSourceLoc &l) { mLine = l; } + + virtual void traverse(TIntermTraverser *) = 0; + virtual TIntermTyped *getAsTyped() { return 0; } + virtual TIntermConstantUnion *getAsConstantUnion() { return 0; } + virtual TIntermAggregate *getAsAggregate() { return 0; } + virtual TIntermBinary *getAsBinaryNode() { return 0; } + virtual TIntermUnary *getAsUnaryNode() { return 0; } + virtual TIntermSelection *getAsSelectionNode() { return 0; } + virtual TIntermSymbol *getAsSymbolNode() { return 0; } + virtual TIntermLoop *getAsLoopNode() { return 0; } + virtual TIntermRaw *getAsRawNode() { return 0; } + + // Replace a child node. Return true if |original| is a child + // node and it is replaced; otherwise, return false. + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement) = 0; + + // For traversing a tree in no particular order, but using + // heap memory. + virtual void enqueueChildren(std::queue *nodeQueue) const = 0; + + protected: + TSourceLoc mLine; +}; + +// +// This is just to help yacc. +// +struct TIntermNodePair +{ + TIntermNode *node1; + TIntermNode *node2; +}; + +// +// Intermediate class for nodes that have a type. +// +class TIntermTyped : public TIntermNode +{ + public: + TIntermTyped(const TType &t) : mType(t) { } + virtual TIntermTyped *getAsTyped() { return this; } + + virtual bool hasSideEffects() const = 0; + + void setType(const TType &t) { mType = t; } + const TType &getType() const { return mType; } + TType *getTypePointer() { return &mType; } + + TBasicType getBasicType() const { return mType.getBasicType(); } + TQualifier getQualifier() const { return mType.getQualifier(); } + TPrecision getPrecision() const { return mType.getPrecision(); } + int getCols() const { return mType.getCols(); } + int getRows() const { return mType.getRows(); } + int getNominalSize() const { return mType.getNominalSize(); } + int getSecondarySize() const { return mType.getSecondarySize(); } + + bool isInterfaceBlock() const { return mType.isInterfaceBlock(); } + bool isMatrix() const { return mType.isMatrix(); } + bool isArray() const { return mType.isArray(); } + bool isVector() const { return mType.isVector(); } + bool isScalar() const { return mType.isScalar(); } + bool isScalarInt() const { return mType.isScalarInt(); } + const char *getBasicString() const { return mType.getBasicString(); } + const char *getQualifierString() const { return mType.getQualifierString(); } + TString getCompleteString() const { return mType.getCompleteString(); } + + int getArraySize() const { return mType.getArraySize(); } + + protected: + TType mType; +}; + +// +// Handle for, do-while, and while loops. +// +enum TLoopType +{ + ELoopFor, + ELoopWhile, + ELoopDoWhile +}; + +class TIntermLoop : public TIntermNode +{ + public: + TIntermLoop(TLoopType type, + TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr, + TIntermNode *body) + : mType(type), + mInit(init), + mCond(cond), + mExpr(expr), + mBody(body), + mUnrollFlag(false) { } + + virtual TIntermLoop *getAsLoopNode() { return this; } + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + TLoopType getType() const { return mType; } + TIntermNode *getInit() { return mInit; } + TIntermTyped *getCondition() { return mCond; } + TIntermTyped *getExpression() { return mExpr; } + TIntermNode *getBody() { return mBody; } + + 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 + TIntermTyped *mCond; // loop exit condition + TIntermTyped *mExpr; // for-loop expression + TIntermNode *mBody; // loop body + + bool mUnrollFlag; // Whether the loop should be unrolled or not. +}; + +// +// Handle break, continue, return, and kill. +// +class TIntermBranch : public TIntermNode +{ + public: + TIntermBranch(TOperator op, TIntermTyped *e) + : mFlowOp(op), + mExpression(e) { } + + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + 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 +}; + +// +// Nodes that correspond to symbols or constants in the source code. +// +class TIntermSymbol : public TIntermTyped +{ + public: + // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. + // If sym comes from per process globalpoolallocator, then it causes increased memory usage + // per compile it is essential to use "symbol = sym" to assign to symbol + TIntermSymbol(int id, const TString &symbol, const TType &type) + : TIntermTyped(type), + mId(id) + { + mSymbol = symbol; + } + + virtual bool hasSideEffects() const { return false; } + + int getId() const { return mId; } + const TString &getSymbol() const { return mSymbol; } + + void setId(int newId) { mId = newId; } + + virtual void traverse(TIntermTraverser *); + virtual TIntermSymbol *getAsSymbolNode() { return this; } + virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } + + virtual void enqueueChildren(std::queue *nodeQueue) const {} + + protected: + int mId; + TString mSymbol; +}; + +// A Raw node stores raw code, that the translator will insert verbatim +// into the output stream. Useful for transformation operations that make +// complex code that might not fit naturally into the GLSL model. +class TIntermRaw : public TIntermTyped +{ + public: + TIntermRaw(const TType &type, const TString &rawText) + : TIntermTyped(type), + mRawText(rawText) { } + + virtual bool hasSideEffects() const { return false; } + + TString getRawText() const { return mRawText; } + + virtual void traverse(TIntermTraverser *); + + virtual TIntermRaw *getAsRawNode() { return this; } + virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } + virtual void enqueueChildren(std::queue *nodeQueue) const {} + + protected: + TString mRawText; +}; + +class TIntermConstantUnion : public TIntermTyped +{ + public: + TIntermConstantUnion(ConstantUnion *unionPointer, const TType &type) + : TIntermTyped(type), + mUnionArrayPointer(unionPointer) { } + + virtual bool hasSideEffects() const { return false; } + + ConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; } + + int getIConst(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0; + } + unsigned int getUConst(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0; + } + float getFConst(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f; + } + bool getBConst(size_t index) const + { + return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false; + } + + virtual TIntermConstantUnion *getAsConstantUnion() { return this; } + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } + + TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &); + + virtual void enqueueChildren(std::queue *nodeQueue) const {} + + protected: + ConstantUnion *mUnionArrayPointer; +}; + +// +// Intermediate class for node types that hold operators. +// +class TIntermOperator : public TIntermTyped +{ + public: + TOperator getOp() const { return mOp; } + void setOp(TOperator op) { mOp = op; } + + bool isAssignment() const; + bool isConstructor() const; + + virtual bool hasSideEffects() const { return isAssignment(); } + + protected: + TIntermOperator(TOperator op) + : TIntermTyped(TType(EbtFloat, EbpUndefined)), + mOp(op) {} + TIntermOperator(TOperator op, const TType &type) + : TIntermTyped(type), + mOp(op) {} + + TOperator mOp; +}; + +// +// Nodes for all the basic binary math operators. +// +class TIntermBinary : public TIntermOperator +{ + public: + TIntermBinary(TOperator op) + : TIntermOperator(op), + mAddIndexClamp(false) {} + + virtual TIntermBinary *getAsBinaryNode() { return this; } + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + virtual bool hasSideEffects() const + { + return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects(); + } + + void setLeft(TIntermTyped *node) { mLeft = node; } + void setRight(TIntermTyped *node) { mRight = node; } + TIntermTyped *getLeft() const { return mLeft; } + TIntermTyped *getRight() const { return mRight; } + bool promote(TInfoSink &); + + void setAddIndexClamp() { mAddIndexClamp = true; } + bool getAddIndexClamp() { return mAddIndexClamp; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; + + protected: + TIntermTyped* mLeft; + TIntermTyped* mRight; + + // If set to true, wrap any EOpIndexIndirect with a clamp to bounds. + bool mAddIndexClamp; +}; + +// +// Nodes for unary math operators. +// +class TIntermUnary : public TIntermOperator +{ + public: + TIntermUnary(TOperator op, const TType &type) + : TIntermOperator(op, type), + mOperand(NULL), + mUseEmulatedFunction(false) {} + TIntermUnary(TOperator op) + : TIntermOperator(op), + mOperand(NULL), + mUseEmulatedFunction(false) {} + + virtual void traverse(TIntermTraverser *); + virtual TIntermUnary *getAsUnaryNode() { return this; } + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + virtual bool hasSideEffects() const + { + return isAssignment() || mOperand->hasSideEffects(); + } + + void setOperand(TIntermTyped *operand) { mOperand = operand; } + TIntermTyped *getOperand() { return mOperand; } + bool promote(TInfoSink &); + + void setUseEmulatedFunction() { mUseEmulatedFunction = true; } + bool getUseEmulatedFunction() { return mUseEmulatedFunction; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; + + protected: + TIntermTyped *mOperand; + + // If set to true, replace the built-in function call with an emulated one + // to work around driver bugs. + bool mUseEmulatedFunction; +}; + +typedef TVector TIntermSequence; +typedef TVector TQualifierList; + +// +// Nodes that operate on an arbitrary sized set of children. +// +class TIntermAggregate : public TIntermOperator +{ + public: + TIntermAggregate() + : TIntermOperator(EOpNull), + mUserDefined(false), + mUseEmulatedFunction(false) { } + TIntermAggregate(TOperator op) + : TIntermOperator(op), + mUseEmulatedFunction(false) { } + ~TIntermAggregate() { } + + virtual TIntermAggregate *getAsAggregate() { return this; } + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + // Conservatively assume function calls and other aggregate operators have side-effects + virtual bool hasSideEffects() const { return true; } + + TIntermSequence *getSequence() { return &mSequence; } + + void setName(const TString &name) { mName = name; } + const TString &getName() const { return mName; } + + void setUserDefined() { mUserDefined = true; } + bool isUserDefined() const { return mUserDefined; } + + void setOptimize(bool optimize) { mOptimize = optimize; } + bool getOptimize() const { return mOptimize; } + void setDebug(bool debug) { mDebug = debug; } + bool getDebug() const { return mDebug; } + + void setUseEmulatedFunction() { mUseEmulatedFunction = true; } + bool getUseEmulatedFunction() { return mUseEmulatedFunction; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; + + protected: + TIntermAggregate(const TIntermAggregate &); // disallow copy constructor + TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator + TIntermSequence mSequence; + TString mName; + bool mUserDefined; // used for user defined function names + + bool mOptimize; + bool mDebug; + + // If set to true, replace the built-in function call with an emulated one + // to work around driver bugs. + bool mUseEmulatedFunction; +}; + +// +// For if tests. Simplified since there is no switch statement. +// +class TIntermSelection : public TIntermTyped +{ + public: + TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB) + : TIntermTyped(TType(EbtVoid, EbpUndefined)), + mCondition(cond), + mTrueBlock(trueB), + mFalseBlock(falseB) {} + TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB, + const TType &type) + : TIntermTyped(type), + mCondition(cond), + mTrueBlock(trueB), + mFalseBlock(falseB) {} + + virtual void traverse(TIntermTraverser *); + virtual bool replaceChildNode( + TIntermNode *original, TIntermNode *replacement); + + // Conservatively assume selections have side-effects + virtual bool hasSideEffects() const { return true; } + + bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } + TIntermNode *getCondition() const { return mCondition; } + TIntermNode *getTrueBlock() const { return mTrueBlock; } + TIntermNode *getFalseBlock() const { return mFalseBlock; } + TIntermSelection *getAsSelectionNode() { return this; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; + +protected: + TIntermTyped *mCondition; + TIntermNode *mTrueBlock; + TIntermNode *mFalseBlock; +}; + +enum Visit +{ + PreVisit, + InVisit, + PostVisit +}; + +// +// For traversing the tree. User should derive from this, +// put their traversal specific data in it, and then pass +// it to a Traverse method. +// +// When using this, just fill in the methods for nodes you want visited. +// Return false from a pre-visit to skip visiting that node's subtree. +// +class TIntermTraverser +{ + public: + POOL_ALLOCATOR_NEW_DELETE(); + // TODO(zmo): remove default values. + TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, + bool rightToLeft = false) + : preVisit(preVisit), + inVisit(inVisit), + postVisit(postVisit), + rightToLeft(rightToLeft), + mDepth(0), + mMaxDepth(0) {} + virtual ~TIntermTraverser() {} + + virtual void visitSymbol(TIntermSymbol *) {} + virtual void visitRaw(TIntermRaw *) {} + virtual void visitConstantUnion(TIntermConstantUnion *) {} + virtual bool visitBinary(Visit, TIntermBinary *) { return true; } + virtual bool visitUnary(Visit, TIntermUnary *) { return true; } + virtual bool visitSelection(Visit, TIntermSelection *) { return true; } + virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; } + virtual bool visitLoop(Visit, TIntermLoop *) { return true; } + virtual bool visitBranch(Visit, TIntermBranch *) { return true; } + + int getMaxDepth() const { return mMaxDepth; } + + void incrementDepth(TIntermNode *current) + { + mDepth++; + mMaxDepth = std::max(mMaxDepth, mDepth); + mPath.push_back(current); + } + + void decrementDepth() + { + mDepth--; + mPath.pop_back(); + } + + TIntermNode *getParentNode() + { + return mPath.size() == 0 ? NULL : mPath.back(); + } + + // Return the original name if hash function pointer is NULL; + // otherwise return the hashed name. + static TString hash(const TString& name, ShHashFunction64 hashFunction); + + const bool preVisit; + const bool inVisit; + const bool postVisit; + const bool rightToLeft; + + protected: + int mDepth; + int mMaxDepth; + + // All the nodes from root to the current node's parent during traversing. + TVector mPath; +}; + +// +// For traversing the tree, and computing max depth. +// Takes a maximum depth limit to prevent stack overflow. +// +class TMaxDepthTraverser : public TIntermTraverser +{ + public: + POOL_ALLOCATOR_NEW_DELETE(); + TMaxDepthTraverser(int depthLimit) + : TIntermTraverser(true, true, false, false), + mDepthLimit(depthLimit) { } + + virtual bool visitBinary(Visit, TIntermBinary *) { return depthCheck(); } + virtual bool visitUnary(Visit, TIntermUnary *) { return depthCheck(); } + virtual bool visitSelection(Visit, TIntermSelection *) { return depthCheck(); } + virtual bool visitAggregate(Visit, TIntermAggregate *) { return depthCheck(); } + virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); } + virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); } + +protected: + bool depthCheck() const { return mMaxDepth < mDepthLimit; } + + int mDepthLimit; +}; + +#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp index 48d2013cc5..72b2033fb3 100644 --- a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp +++ b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // // Traverse the intermediate representation tree, and diff --git a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp index fa0c9f7748..ef4f83307c 100644 --- a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp @@ -12,122 +12,10 @@ #include #include -#include "compiler/translator/HashNames.h" -#include "compiler/translator/localintermediate.h" -#include "compiler/translator/QualifierAlive.h" +#include "compiler/translator/Intermediate.h" #include "compiler/translator/RemoveTree.h" #include "compiler/translator/SymbolTable.h" -namespace -{ - -TPrecision GetHigherPrecision(TPrecision left, TPrecision right) -{ - return left > right ? left : right; -} - -bool ValidateMultiplication(TOperator op, const TType &left, const TType &right) -{ - switch (op) - { - case EOpMul: - case EOpMulAssign: - return left.getNominalSize() == right.getNominalSize() && - left.getSecondarySize() == right.getSecondarySize(); - case EOpVectorTimesScalar: - case EOpVectorTimesScalarAssign: - return true; - case EOpVectorTimesMatrix: - return left.getNominalSize() == right.getRows(); - case EOpVectorTimesMatrixAssign: - return left.getNominalSize() == right.getRows() && - left.getNominalSize() == right.getCols(); - case EOpMatrixTimesVector: - return left.getCols() == right.getNominalSize(); - case EOpMatrixTimesScalar: - case EOpMatrixTimesScalarAssign: - return true; - case EOpMatrixTimesMatrix: - return left.getCols() == right.getRows(); - case EOpMatrixTimesMatrixAssign: - return left.getCols() == right.getCols() && - left.getRows() == right.getRows(); - - default: - UNREACHABLE(); - return false; - } -} - -bool CompareStructure(const TType& leftNodeType, - ConstantUnion *rightUnionArray, - ConstantUnion *leftUnionArray); - -bool CompareStruct(const TType &leftNodeType, - ConstantUnion *rightUnionArray, - ConstantUnion *leftUnionArray) -{ - const TFieldList &fields = leftNodeType.getStruct()->fields(); - - size_t structSize = fields.size(); - size_t index = 0; - - for (size_t j = 0; j < structSize; j++) - { - size_t size = fields[j]->type()->getObjectSize(); - for (size_t i = 0; i < size; i++) - { - if (fields[j]->type()->getBasicType() == EbtStruct) - { - if (!CompareStructure(*fields[j]->type(), - &rightUnionArray[index], - &leftUnionArray[index])) - { - return false; - } - } - else - { - if (leftUnionArray[index] != rightUnionArray[index]) - return false; - index++; - } - } - } - return true; -} - -bool CompareStructure(const TType &leftNodeType, - ConstantUnion *rightUnionArray, - ConstantUnion *leftUnionArray) -{ - if (leftNodeType.isArray()) - { - TType typeWithoutArrayness = leftNodeType; - typeWithoutArrayness.clearArrayness(); - - size_t arraySize = leftNodeType.getArraySize(); - - for (size_t i = 0; i < arraySize; ++i) - { - size_t offset = typeWithoutArrayness.getObjectSize() * i; - if (!CompareStruct(typeWithoutArrayness, - &rightUnionArray[offset], - &leftUnionArray[offset])) - { - return false; - } - } - } - else - { - return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); - } - return true; -} - -} // namespace anonymous - //////////////////////////////////////////////////////////////////////////// // // First set of functions are to help build the intermediate representation. @@ -630,982 +518,3 @@ void TIntermediate::remove(TIntermNode *root) if (root) RemoveAllTreeNodes(root); } - -//////////////////////////////////////////////////////////////// -// -// Member functions of the nodes used for building the tree. -// -//////////////////////////////////////////////////////////////// - -#define REPLACE_IF_IS(node, type, original, replacement) \ - if (node == original) { \ - node = static_cast(replacement); \ - return true; \ - } - -bool TIntermLoop::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mInit, TIntermNode, original, replacement); - REPLACE_IF_IS(mCond, TIntermTyped, original, replacement); - REPLACE_IF_IS(mExpr, TIntermTyped, original, replacement); - REPLACE_IF_IS(mBody, TIntermNode, original, replacement); - 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) -{ - REPLACE_IF_IS(mExpression, TIntermTyped, original, replacement); - return false; -} - -void TIntermBranch::enqueueChildren(std::queue *nodeQueue) const -{ - if (mExpression) - { - nodeQueue->push(mExpression); - } -} - -bool TIntermBinary::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mLeft, TIntermTyped, original, replacement); - REPLACE_IF_IS(mRight, TIntermTyped, original, replacement); - 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) -{ - REPLACE_IF_IS(mOperand, TIntermTyped, original, replacement); - return false; -} - -void TIntermUnary::enqueueChildren(std::queue *nodeQueue) const -{ - if (mOperand) - { - nodeQueue->push(mOperand); - } -} - -bool TIntermAggregate::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - for (size_t ii = 0; ii < mSequence.size(); ++ii) - { - REPLACE_IF_IS(mSequence[ii], TIntermNode, original, replacement); - } - return false; -} - -void TIntermAggregate::enqueueChildren(std::queue *nodeQueue) const -{ - for (size_t childIndex = 0; childIndex < mSequence.size(); childIndex++) - { - nodeQueue->push(mSequence[childIndex]); - } -} - -bool TIntermSelection::replaceChildNode( - TIntermNode *original, TIntermNode *replacement) -{ - REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); - REPLACE_IF_IS(mTrueBlock, TIntermNode, original, replacement); - REPLACE_IF_IS(mFalseBlock, TIntermNode, original, replacement); - return false; -} - -void TIntermSelection::enqueueChildren(std::queue *nodeQueue) const -{ - if (mCondition) - { - nodeQueue->push(mCondition); - } - if (mTrueBlock) - { - nodeQueue->push(mTrueBlock); - } - if (mFalseBlock) - { - nodeQueue->push(mFalseBlock); - } -} - -// -// Say whether or not an operation node changes the value of a variable. -// -bool TIntermOperator::isAssignment() const -{ - switch (mOp) - { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - case EOpAssign: - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - case EOpDivAssign: - return true; - default: - return false; - } -} - -// -// returns true if the operator is for one of the constructors -// -bool TIntermOperator::isConstructor() const -{ - switch (mOp) - { - case EOpConstructVec2: - case EOpConstructVec3: - case EOpConstructVec4: - case EOpConstructMat2: - case EOpConstructMat3: - case EOpConstructMat4: - case EOpConstructFloat: - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructInt: - case EOpConstructUVec2: - case EOpConstructUVec3: - case EOpConstructUVec4: - case EOpConstructUInt: - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructBool: - case EOpConstructStruct: - return true; - default: - return false; - } -} - -// -// Make sure the type of a unary operator is appropriate for its -// combination of operation and operand type. -// -// Returns false in nothing makes sense. -// -bool TIntermUnary::promote(TInfoSink &) -{ - switch (mOp) - { - case EOpLogicalNot: - if (mOperand->getBasicType() != EbtBool) - return false; - break; - case EOpNegative: - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - if (mOperand->getBasicType() == EbtBool) - return false; - break; - - // operators for built-ins are already type checked against their prototype - case EOpAny: - case EOpAll: - case EOpVectorLogicalNot: - return true; - - default: - if (mOperand->getBasicType() != EbtFloat) - return false; - } - - setType(mOperand->getType()); - mType.setQualifier(EvqTemporary); - - return true; -} - -// -// Establishes the type of the resultant operation, as well as -// makes the operator the correct one for the operands. -// -// Returns false if operator can't work on operands. -// -bool TIntermBinary::promote(TInfoSink &infoSink) -{ - // This function only handles scalars, vectors, and matrices. - if (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; - } - - // - // Base assumption: just make the type the same as the left - // operand. Then only deviations from this need be coded. - // - setType(mLeft->getType()); - - // The result gets promoted to the highest precision. - TPrecision higherPrecision = GetHigherPrecision( - mLeft->getPrecision(), mRight->getPrecision()); - getTypePointer()->setPrecision(higherPrecision); - - // Binary operations results in temporary variables unless both - // operands are const. - if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst) - { - getTypePointer()->setQualifier(EvqTemporary); - } - - const int nominalSize = - std::max(mLeft->getNominalSize(), mRight->getNominalSize()); - - // - // All scalars or structs. Code after this test assumes this case is removed! - // - if (nominalSize == 1) - { - switch (mOp) - { - // - // Promote to conditional - // - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - setType(TType(EbtBool, EbpUndefined)); - break; - - // - // And and Or operate on conditionals - // - case EOpLogicalAnd: - case EOpLogicalOr: - // Both operands must be of type bool. - if (mLeft->getBasicType() != EbtBool || mRight->getBasicType() != EbtBool) - { - return false; - } - setType(TType(EbtBool, EbpUndefined)); - break; - - default: - break; - } - return true; - } - - // If we reach here, at least one of the operands is vector or matrix. - // The other operand could be a scalar, vector, or matrix. - // Can these two operands be combined? - // - TBasicType basicType = mLeft->getBasicType(); - switch (mOp) - { - case EOpMul: - if (!mLeft->isMatrix() && mRight->isMatrix()) - { - if (mLeft->isVector()) - { - mOp = EOpVectorTimesMatrix; - setType(TType(basicType, higherPrecision, EvqTemporary, - mRight->getCols(), 1)); - } - else - { - mOp = EOpMatrixTimesScalar; - setType(TType(basicType, higherPrecision, EvqTemporary, - mRight->getCols(), mRight->getRows())); - } - } - else if (mLeft->isMatrix() && !mRight->isMatrix()) - { - if (mRight->isVector()) - { - mOp = EOpMatrixTimesVector; - setType(TType(basicType, higherPrecision, EvqTemporary, - mLeft->getRows(), 1)); - } - else - { - mOp = EOpMatrixTimesScalar; - } - } - else if (mLeft->isMatrix() && mRight->isMatrix()) - { - mOp = EOpMatrixTimesMatrix; - setType(TType(basicType, higherPrecision, EvqTemporary, - mRight->getCols(), mLeft->getRows())); - } - else if (!mLeft->isMatrix() && !mRight->isMatrix()) - { - if (mLeft->isVector() && mRight->isVector()) - { - // leave as component product - } - else if (mLeft->isVector() || mRight->isVector()) - { - mOp = EOpVectorTimesScalar; - setType(TType(basicType, higherPrecision, EvqTemporary, - nominalSize, 1)); - } - } - else - { - infoSink.info.message(EPrefixInternalError, getLine(), - "Missing elses"); - return false; - } - - if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType())) - { - return false; - } - break; - - case EOpMulAssign: - if (!mLeft->isMatrix() && mRight->isMatrix()) - { - if (mLeft->isVector()) - { - mOp = EOpVectorTimesMatrixAssign; - } - else - { - return false; - } - } - else if (mLeft->isMatrix() && !mRight->isMatrix()) - { - if (mRight->isVector()) - { - return false; - } - else - { - mOp = EOpMatrixTimesScalarAssign; - } - } - else if (mLeft->isMatrix() && mRight->isMatrix()) - { - mOp = EOpMatrixTimesMatrixAssign; - setType(TType(basicType, higherPrecision, EvqTemporary, - mRight->getCols(), mLeft->getRows())); - } - else if (!mLeft->isMatrix() && !mRight->isMatrix()) - { - if (mLeft->isVector() && mRight->isVector()) - { - // leave as component product - } - else if (mLeft->isVector() || mRight->isVector()) - { - if (!mLeft->isVector()) - return false; - mOp = EOpVectorTimesScalarAssign; - setType(TType(basicType, higherPrecision, EvqTemporary, - mLeft->getNominalSize(), 1)); - } - } - else - { - infoSink.info.message(EPrefixInternalError, getLine(), - "Missing elses"); - return false; - } - - if (!ValidateMultiplication(mOp, mLeft->getType(), mRight->getType())) - { - return false; - } - break; - - case EOpAssign: - case EOpInitialize: - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - if ((mLeft->isMatrix() && mRight->isVector()) || - (mLeft->isVector() && mRight->isMatrix())) - { - return false; - } - - // Are the sizes compatible? - 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 (!mLeft->isScalar() && !mRight->isScalar()) - return false; - - // Operator cannot be of type pure assignment. - if (mOp == EOpAssign || mOp == EOpInitialize) - return false; - } - - { - const int secondarySize = std::max( - mLeft->getSecondarySize(), mRight->getSecondarySize()); - setType(TType(basicType, higherPrecision, EvqTemporary, - nominalSize, secondarySize)); - } - break; - - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if ((mLeft->getNominalSize() != mRight->getNominalSize()) || - (mLeft->getSecondarySize() != mRight->getSecondarySize())) - { - return false; - } - setType(TType(EbtBool, EbpUndefined)); - break; - - default: - return false; - } - return true; -} - -// -// The fold functions see if an operation on a constant can be done in place, -// without generating run-time code. -// -// Returns the node to keep using, which may or may not be the node passed in. -// -TIntermTyped *TIntermConstantUnion::fold( - TOperator op, TIntermTyped *constantNode, TInfoSink &infoSink) -{ - ConstantUnion *unionArray = getUnionArrayPointer(); - - if (!unionArray) - return NULL; - - size_t objectSize = getType().getObjectSize(); - - if (constantNode) - { - // binary operations - TIntermConstantUnion *node = constantNode->getAsConstantUnion(); - ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); - TType returnType = getType(); - - if (!rightUnionArray) - return NULL; - - // for a case like float f = 1.2 + vec4(2,3,4,5); - if (constantNode->getType().getObjectSize() == 1 && objectSize > 1) - { - rightUnionArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; ++i) - { - rightUnionArray[i] = *node->getUnionArrayPointer(); - } - returnType = getType(); - } - else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) - { - // for a case like float f = vec4(2,3,4,5) + 1.2; - unionArray = new ConstantUnion[constantNode->getType().getObjectSize()]; - for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) - { - unionArray[i] = *getUnionArrayPointer(); - } - returnType = node->getType(); - objectSize = constantNode->getType().getObjectSize(); - } - - ConstantUnion *tempConstArray = NULL; - TIntermConstantUnion *tempNode; - - bool boolNodeFlag = false; - switch(op) - { - case EOpAdd: - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] + rightUnionArray[i]; - break; - case EOpSub: - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] - rightUnionArray[i]; - break; - - case EOpMul: - case EOpVectorTimesScalar: - case EOpMatrixTimesScalar: - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] * rightUnionArray[i]; - break; - - case EOpMatrixTimesMatrix: - { - if (getType().getBasicType() != EbtFloat || - node->getBasicType() != EbtFloat) - { - infoSink.info.message( - EPrefixInternalError, getLine(), - "Constant Folding cannot be done for matrix multiply"); - return NULL; - } - - const int leftCols = getCols(); - const int leftRows = getRows(); - const int rightCols = constantNode->getType().getCols(); - const int rightRows = constantNode->getType().getRows(); - const int resultCols = rightCols; - const int resultRows = leftRows; - - tempConstArray = new ConstantUnion[resultCols*resultRows]; - for (int row = 0; row < resultRows; row++) - { - for (int column = 0; column < resultCols; column++) - { - tempConstArray[resultRows * column + row].setFConst(0.0f); - for (int i = 0; i < leftCols; i++) - { - tempConstArray[resultRows * column + row].setFConst( - tempConstArray[resultRows * column + row].getFConst() + - unionArray[i * leftRows + row].getFConst() * - rightUnionArray[column * rightRows + i].getFConst()); - } - } - } - - // update return type for matrix product - returnType.setPrimarySize(resultCols); - returnType.setSecondarySize(resultRows); - } - break; - - case EOpDiv: - { - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - switch (getType().getBasicType()) - { - case EbtFloat: - if (rightUnionArray[i] == 0.0f) - { - infoSink.info.message( - EPrefixWarning, getLine(), - "Divide by zero error during constant folding"); - tempConstArray[i].setFConst( - unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX); - } - else - { - tempConstArray[i].setFConst( - unionArray[i].getFConst() / - rightUnionArray[i].getFConst()); - } - break; - - case EbtInt: - if (rightUnionArray[i] == 0) - { - infoSink.info.message( - EPrefixWarning, getLine(), - "Divide by zero error during constant folding"); - tempConstArray[i].setIConst(INT_MAX); - } - else - { - tempConstArray[i].setIConst( - unionArray[i].getIConst() / - rightUnionArray[i].getIConst()); - } - break; - - case EbtUInt: - if (rightUnionArray[i] == 0) - { - infoSink.info.message( - EPrefixWarning, getLine(), - "Divide by zero error during constant folding"); - tempConstArray[i].setUConst(UINT_MAX); - } - else - { - tempConstArray[i].setUConst( - unionArray[i].getUConst() / - rightUnionArray[i].getUConst()); - } - break; - - default: - infoSink.info.message( - EPrefixInternalError, getLine(), - "Constant folding cannot be done for \"/\""); - return NULL; - } - } - } - break; - - case EOpMatrixTimesVector: - { - if (node->getBasicType() != EbtFloat) - { - infoSink.info.message( - EPrefixInternalError, getLine(), - "Constant Folding cannot be done for matrix times vector"); - return NULL; - } - - const int matrixCols = getCols(); - const int matrixRows = getRows(); - - tempConstArray = new ConstantUnion[matrixRows]; - - for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) - { - tempConstArray[matrixRow].setFConst(0.0f); - for (int col = 0; col < matrixCols; col++) - { - tempConstArray[matrixRow].setFConst( - tempConstArray[matrixRow].getFConst() + - unionArray[col * matrixRows + matrixRow].getFConst() * - rightUnionArray[col].getFConst()); - } - } - - returnType = node->getType(); - returnType.setPrimarySize(matrixRows); - - tempNode = new TIntermConstantUnion(tempConstArray, returnType); - tempNode->setLine(getLine()); - - return tempNode; - } - - case EOpVectorTimesMatrix: - { - if (getType().getBasicType() != EbtFloat) - { - infoSink.info.message( - EPrefixInternalError, getLine(), - "Constant Folding cannot be done for vector times matrix"); - return NULL; - } - - const int matrixCols = constantNode->getType().getCols(); - const int matrixRows = constantNode->getType().getRows(); - - tempConstArray = new ConstantUnion[matrixCols]; - - for (int matrixCol = 0; matrixCol < matrixCols; matrixCol++) - { - tempConstArray[matrixCol].setFConst(0.0f); - for (int matrixRow = 0; matrixRow < matrixRows; matrixRow++) - { - tempConstArray[matrixCol].setFConst( - tempConstArray[matrixCol].getFConst() + - unionArray[matrixRow].getFConst() * - rightUnionArray[matrixCol * matrixRows + matrixRow].getFConst()); - } - } - - returnType.setPrimarySize(matrixCols); - } - break; - - case EOpLogicalAnd: - // this code is written for possible future use, - // will not get executed currently - { - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - tempConstArray[i] = unionArray[i] && rightUnionArray[i]; - } - } - break; - - case EOpLogicalOr: - // this code is written for possible future use, - // will not get executed currently - { - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - tempConstArray[i] = unionArray[i] || rightUnionArray[i]; - } - } - break; - - case EOpLogicalXor: - { - tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - switch (getType().getBasicType()) - { - case EbtBool: - tempConstArray[i].setBConst( - unionArray[i] == rightUnionArray[i] ? false : true); - break; - default: - UNREACHABLE(); - break; - } - } - } - break; - - case EOpLessThan: - ASSERT(objectSize == 1); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(*unionArray < *rightUnionArray); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - - case EOpGreaterThan: - ASSERT(objectSize == 1); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(*unionArray > *rightUnionArray); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - - case EOpLessThanEqual: - { - ASSERT(objectSize == 1); - ConstantUnion constant; - constant.setBConst(*unionArray > *rightUnionArray); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(!constant.getBConst()); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - } - - case EOpGreaterThanEqual: - { - ASSERT(objectSize == 1); - ConstantUnion constant; - constant.setBConst(*unionArray < *rightUnionArray); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(!constant.getBConst()); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; - } - - case EOpEqual: - if (getType().getBasicType() == EbtStruct) - { - if (!CompareStructure(node->getType(), - node->getUnionArrayPointer(), - unionArray)) - { - boolNodeFlag = true; - } - } - else - { - for (size_t i = 0; i < objectSize; i++) - { - if (unionArray[i] != rightUnionArray[i]) - { - boolNodeFlag = true; - break; // break out of for loop - } - } - } - - tempConstArray = new ConstantUnion[1]; - if (!boolNodeFlag) - { - tempConstArray->setBConst(true); - } - else - { - tempConstArray->setBConst(false); - } - - tempNode = new TIntermConstantUnion( - tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); - tempNode->setLine(getLine()); - - return tempNode; - - case EOpNotEqual: - if (getType().getBasicType() == EbtStruct) - { - if (CompareStructure(node->getType(), - node->getUnionArrayPointer(), - unionArray)) - { - boolNodeFlag = true; - } - } - else - { - for (size_t i = 0; i < objectSize; i++) - { - if (unionArray[i] == rightUnionArray[i]) - { - boolNodeFlag = true; - break; // break out of for loop - } - } - } - - tempConstArray = new ConstantUnion[1]; - if (!boolNodeFlag) - { - tempConstArray->setBConst(true); - } - else - { - tempConstArray->setBConst(false); - } - - tempNode = new TIntermConstantUnion( - tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); - tempNode->setLine(getLine()); - - return tempNode; - - default: - infoSink.info.message( - EPrefixInternalError, getLine(), - "Invalid operator for constant folding"); - return NULL; - } - tempNode = new TIntermConstantUnion(tempConstArray, returnType); - tempNode->setLine(getLine()); - - return tempNode; - } - else - { - // - // Do unary operations - // - TIntermConstantUnion *newNode = 0; - ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) - { - switch(op) - { - case EOpNegative: - switch (getType().getBasicType()) - { - case EbtFloat: - tempConstArray[i].setFConst(-unionArray[i].getFConst()); - break; - case EbtInt: - tempConstArray[i].setIConst(-unionArray[i].getIConst()); - break; - case EbtUInt: - tempConstArray[i].setUConst(static_cast( - -static_cast(unionArray[i].getUConst()))); - break; - default: - infoSink.info.message( - EPrefixInternalError, getLine(), - "Unary operation not folded into constant"); - return NULL; - } - break; - - case EOpLogicalNot: - // this code is written for possible future use, - // will not get executed currently - switch (getType().getBasicType()) - { - case EbtBool: - tempConstArray[i].setBConst(!unionArray[i].getBConst()); - break; - default: - infoSink.info.message( - EPrefixInternalError, getLine(), - "Unary operation not folded into constant"); - return NULL; - } - break; - - default: - return NULL; - } - } - newNode = new TIntermConstantUnion(tempConstArray, getType()); - newNode->setLine(getLine()); - return newNode; - } -} - -// static -TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction) -{ - if (hashFunction == NULL || name.empty()) - return name; - khronos_uint64_t number = (*hashFunction)(name.c_str(), name.length()); - TStringStream stream; - stream << HASHED_NAME_PREFIX << std::hex << number; - TString hashedName = stream.str(); - return hashedName; -} diff --git a/src/3rdparty/angle/src/compiler/translator/LoopInfo.h b/src/3rdparty/angle/src/compiler/translator/LoopInfo.h index 5a140c339e..5f72a6e944 100644 --- a/src/3rdparty/angle/src/compiler/translator/LoopInfo.h +++ b/src/3rdparty/angle/src/compiler/translator/LoopInfo.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TRANSLATOR_LOOP_INFO_H_ #define COMPILER_TRANSLATOR_LOOP_INFO_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class TLoopIndexInfo { diff --git a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h index b58c7ec689..60070c9d33 100644 --- a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h +++ b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h @@ -9,7 +9,7 @@ #ifndef TRANSLATOR_NODESEARCH_H_ #define TRANSLATOR_NODESEARCH_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp index 7839c04852..6d07cccc04 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp @@ -81,9 +81,10 @@ void TOutputGLSLBase::writeVariableType(const TType &type) { TInfoSinkBase &out = objSink(); TQualifier qualifier = type.getQualifier(); - // TODO(alokp): Validate qualifier for variable declarations. if (qualifier != EvqTemporary && qualifier != EvqGlobal) + { out << type.getQualifierString() << " "; + } // Declare the struct if we have not done so already. if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct())) { @@ -648,6 +649,17 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) mDeclaringVariables = false; } break; + case EOpInvariantDeclaration: { + // Invariant declaration. + ASSERT(visit == PreVisit); + const TIntermSequence *sequence = node->getSequence(); + ASSERT(sequence && sequence->size() == 1); + const TIntermSymbol *symbol = sequence->front()->getAsSymbolNode(); + ASSERT(symbol); + out << "invariant " << symbol->getSymbol() << ";"; + visitChildren = false; + break; + } case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break; diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h index 42364de6f5..e5174f5660 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h @@ -9,7 +9,7 @@ #include -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/LoopInfo.h" #include "compiler/translator/ParseContext.h" diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp index 1bf1181af0..a5ea71599d 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp @@ -21,6 +21,7 @@ #include "compiler/translator/util.h" #include "compiler/translator/UniformHLSL.h" #include "compiler/translator/StructureHLSL.h" +#include "compiler/translator/TranslatorHLSL.h" #include #include @@ -93,8 +94,10 @@ bool OutputHLSL::TextureFunction::operator<(const TextureFunction &rhs) const return false; } -OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType) - : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType) +OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator) + : TIntermTraverser(true, true, true), + mContext(context), + mOutputType(parentTranslator->getOutputType()) { mUnfoldShortCircuit = new UnfoldShortCircuit(context, this); mInsideFunction = false; @@ -126,6 +129,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc mUsesDiscardRewriting = false; mUsesNestedBreak = false; + const ShBuiltInResources &resources = parentTranslator->getResources(); mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; mUniqueIndex = 0; @@ -138,7 +142,7 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc mExcessiveLoopIndex = NULL; mStructureHLSL = new StructureHLSL; - mUniformHLSL = new UniformHLSL(mStructureHLSL, mOutputType); + mUniformHLSL = new UniformHLSL(mStructureHLSL, parentTranslator); if (mOutputType == SH_HLSL9_OUTPUT) { @@ -212,31 +216,6 @@ TInfoSinkBase &OutputHLSL::getBodyStream() return mBody; } -const std::vector &OutputHLSL::getUniforms() -{ - return mUniformHLSL->getUniforms(); -} - -const std::vector &OutputHLSL::getInterfaceBlocks() const -{ - return mUniformHLSL->getInterfaceBlocks(); -} - -const std::vector &OutputHLSL::getOutputVariables() const -{ - return mActiveOutputVariables; -} - -const std::vector &OutputHLSL::getAttributes() const -{ - return mActiveAttributes; -} - -const std::vector &OutputHLSL::getVaryings() const -{ - return mActiveVaryings; -} - const std::map &OutputHLSL::getInterfaceBlockRegisterMap() const { return mUniformHLSL->getInterfaceBlockRegisterMap(); @@ -324,8 +303,6 @@ void OutputHLSL::header() // Program linking depends on this exact format varyings += "static " + InterpolationString(type.getQualifier()) + " " + TypeString(type) + " " + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n"; - - declareVaryingToList(type, type.getQualifier(), name, mActiveVaryings); } for (ReferencedSymbols::const_iterator attribute = mReferencedAttributes.begin(); attribute != mReferencedAttributes.end(); attribute++) @@ -334,10 +311,6 @@ void OutputHLSL::header() const TString &name = attribute->second->getSymbol(); attributes += "static " + TypeString(type) + " " + Decorate(name) + ArrayString(type) + " = " + initializer(type) + ";\n"; - - sh::Attribute attributeVar(GLVariableType(type), GLVariablePrecision(type), name.c_str(), - (unsigned int)type.getArraySize(), type.getLayoutQualifier().location); - mActiveAttributes.push_back(attributeVar); } out << mStructureHLSL->structsHeader(); @@ -370,14 +343,9 @@ void OutputHLSL::header() { const TString &variableName = outputVariableIt->first; const TType &variableType = outputVariableIt->second->getType(); - const TLayoutQualifier &layoutQualifier = variableType.getLayoutQualifier(); out << "static " + TypeString(variableType) + " out_" + variableName + ArrayString(variableType) + " = " + initializer(variableType) + ";\n"; - - sh::Attribute outputVar(GLVariableType(variableType), GLVariablePrecision(variableType), variableName.c_str(), - (unsigned int)variableType.getArraySize(), layoutQualifier.location); - mActiveOutputVariables.push_back(outputVar); } } else @@ -1951,6 +1919,9 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) out << ", "; } break; + case EOpInvariantDeclaration: + // Do not do any translation + return false; case EOpPrototype: if (visit == PreVisit) { @@ -2910,29 +2881,4 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con return constUnion; } -class DeclareVaryingTraverser : public GetVariableTraverser -{ - public: - DeclareVaryingTraverser(std::vector *output, - InterpolationType interpolation) - : GetVariableTraverser(output), - mInterpolation(interpolation) - {} - - private: - void visitVariable(Varying *varying) - { - varying->interpolation = mInterpolation; - } - - InterpolationType mInterpolation; -}; - -void OutputHLSL::declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, - const TString &name, std::vector &fieldsOut) -{ - DeclareVaryingTraverser traverser(&fieldsOut, GetInterpolationType(baseTypeQualifier)); - traverser.traverse(type, name); -} - } diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h index 78bb741a11..bec02479bb 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h @@ -12,9 +12,9 @@ #include #include "angle_gl.h" -#include "compiler/translator/intermediate.h" + +#include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" -#include "common/shadervars.h" namespace sh { @@ -27,17 +27,12 @@ typedef std::map ReferencedSymbols; class OutputHLSL : public TIntermTraverser { public: - OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType); + OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator); ~OutputHLSL(); void output(); TInfoSinkBase &getBodyStream(); - const std::vector &getUniforms(); - const std::vector &getInterfaceBlocks() const; - const std::vector &getOutputVariables() const; - const std::vector &getAttributes() const; - const std::vector &getVaryings() const; const std::map &getInterfaceBlockRegisterMap() const; const std::map &getUniformRegisterMap() const; @@ -155,13 +150,8 @@ class OutputHLSL : public TIntermTraverser TIntermSymbol *mExcessiveLoopIndex; - void declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, const TString &name, std::vector& fieldsOut); - TString structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName); - std::vector mActiveOutputVariables; - std::vector mActiveAttributes; - std::vector mActiveVaryings; std::map mFlaggedStructMappedNames; std::map mFlaggedStructOriginalNames; diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp index 605612ac37..ff0a49667c 100644 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp @@ -1018,6 +1018,45 @@ void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* nam // ///////////////////////////////////////////////////////////////////////////////// +const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location, + const TString *name, + const TSymbol *symbol) +{ + const TVariable *variable = NULL; + + if (!symbol) + { + error(location, "undeclared identifier", name->c_str()); + recover(); + } + else if (!symbol->isVariable()) + { + error(location, "variable expected", name->c_str()); + recover(); + } + else + { + variable = static_cast(symbol); + + if (symbolTable.findBuiltIn(variable->getName(), shaderVersion) && + !variable->getExtension().empty() && + extensionErrorCheck(location, variable->getExtension())) + { + recover(); + } + } + + if (!variable) + { + TType type(EbtFloat, EbpUndefined); + TVariable *fakeVariable = new TVariable(name, type); + symbolTable.declare(fakeVariable); + variable = fakeVariable; + } + + return variable; +} + // // Look up a function name in the symbol table, and make sure it is a function. // @@ -1050,6 +1089,8 @@ const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* // Initializers show up in several places in the grammar. Have one set of // code to handle them here. // +// Returns true on error, false if no error +// bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& identifier, TPublicType& pType, TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) { @@ -1308,14 +1349,40 @@ TIntermAggregate* TParseContext::parseSingleInitDeclaration(TPublicType &publicT } } -TIntermAggregate* TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier) +TIntermAggregate* TParseContext::parseInvariantDeclaration(const TSourceLoc &invariantLoc, + const TSourceLoc &identifierLoc, + const TString *identifier, + const TSymbol *symbol) { - if (publicType.type == EbtInvariant && !identifierSymbol) + // invariant declaration + if (globalErrorCheck(invariantLoc, symbolTable.atGlobalLevel(), "invariant varying")) + { + recover(); + } + + if (!symbol) { - error(identifierLocation, "undeclared identifier declared as invariant", identifier.c_str()); + error(identifierLoc, "undeclared identifier declared as invariant", identifier->c_str()); recover(); + + return NULL; } + else + { + const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol); + ASSERT(variable); + const TType &type = variable->getType(); + TIntermSymbol *intermSymbol = intermediate.addSymbol(variable->getUniqueId(), + *identifier, type, identifierLoc); + TIntermAggregate *aggregate = intermediate.makeAggregate(intermSymbol, identifierLoc); + aggregate->setOp(EOpInvariantDeclaration); + return aggregate; + } +} + +TIntermAggregate* TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier) +{ TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation); TIntermAggregate* intermAggregate = intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation); @@ -1548,7 +1615,7 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, const TType for (size_t i = 0; i < fields.size(); i++) { - if ((*args)[i]->getAsTyped()->getType() != *fields[i]->type()) + if (i >= args->size() || (*args)[i]->getAsTyped()->getType() != *fields[i]->type()) { error(line, "Structure constructor arguments do not match structure fields", "Error"); recover(); diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.h b/src/3rdparty/angle/src/compiler/translator/ParseContext.h index a402eec78e..1f4cbdeba9 100644 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.h +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.h @@ -9,7 +9,7 @@ #include "compiler/translator/Compiler.h" #include "compiler/translator/Diagnostics.h" #include "compiler/translator/DirectiveHandler.h" -#include "compiler/translator/localintermediate.h" +#include "compiler/translator/Intermediate.h" #include "compiler/translator/SymbolTable.h" #include "compiler/preprocessor/Preprocessor.h" @@ -77,6 +77,9 @@ struct TParseContext { void trace(const char* str); void recover(); + // This method is guaranteed to succeed, even if no variable with 'name' exists. + const TVariable *getNamedVariable(const TSourceLoc &location, const TString *name, const TSymbol *symbol); + bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc& line); bool parseMatrixFields(const TString&, int matCols, int matRows, TMatrixFields&, const TSourceLoc& line); @@ -126,6 +129,8 @@ struct TParseContext { TIntermAggregate* parseSingleDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier); TIntermAggregate* parseSingleArrayDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& indexLocation, TIntermTyped *indexExpression); TIntermAggregate* parseSingleInitDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer); + TIntermAggregate* parseInvariantDeclaration(const TSourceLoc &invariantLoc, const TSourceLoc &identifierLoc, const TString *identifier, const TSymbol *symbol); + TIntermAggregate* parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier); TIntermAggregate* parseArrayDeclarator(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& arrayLocation, TIntermNode *declaratorList, TIntermTyped *indexExpression); TIntermAggregate* parseInitDeclarator(TPublicType &publicType, TIntermAggregate *declaratorList, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer); diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp index 1ba087e176..1f6fb75821 100644 --- a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp +++ b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class TAliveTraverser : public TIntermTraverser { public: diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp new file mode 100644 index 0000000000..767b18085c --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.cpp @@ -0,0 +1,82 @@ +// +// 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/RegenerateStructNames.h" +#include "compiler/translator/compilerdebug.h" + +void RegenerateStructNames::visitSymbol(TIntermSymbol *symbol) +{ + ASSERT(symbol); + TType *type = symbol->getTypePointer(); + ASSERT(type); + TStructure *userType = type->getStruct(); + if (!userType) + return; + + if (mSymbolTable.findBuiltIn(userType->name(), mShaderVersion)) + { + // Built-in struct, do not touch it. + return; + } + + int uniqueId = userType->uniqueId(); + + ASSERT(mScopeDepth > 0); + if (mScopeDepth == 1) + { + // If a struct is defined at global scope, we don't map its name. + // This is because at global level, the struct might be used to + // declare a uniform, so the same name needs to stay the same for + // vertex/fragment shaders. However, our mapping uses internal ID, + // which will be different for the same struct in vertex/fragment + // shaders. + // This is OK because names for any structs defined in other scopes + // will begin with "_webgl", which is reserved. So there will be + // no conflicts among unmapped struct names from global scope and + // mapped struct names from other scopes. + // However, we need to keep track of these global structs, so if a + // variable is used in a local scope, we don't try to modify the + // struct name through that variable. + mDeclaredGlobalStructs.insert(uniqueId); + return; + } + if (mDeclaredGlobalStructs.count(uniqueId) > 0) + return; + // Map {name} to _webgl_struct_{uniqueId}_{name}. + const char kPrefix[] = "_webgl_struct_"; + if (userType->name().find(kPrefix) == 0) + { + // The name has already been regenerated. + return; + } + std::string id = Str(uniqueId); + TString tmp = kPrefix + TString(id.c_str()); + tmp += "_" + userType->name(); + userType->setName(tmp); +} + +bool RegenerateStructNames::visitAggregate(Visit, TIntermAggregate *aggregate) +{ + ASSERT(aggregate); + switch (aggregate->getOp()) + { + case EOpSequence: + ++mScopeDepth; + { + TIntermSequence &sequence = *(aggregate->getSequence()); + for (size_t ii = 0; ii < sequence.size(); ++ii) + { + TIntermNode *node = sequence[ii]; + ASSERT(node != NULL); + node->traverse(this); + } + } + --mScopeDepth; + return false; + default: + return true; + } +} diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h new file mode 100644 index 0000000000..ac87600347 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h @@ -0,0 +1,40 @@ +// +// 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_REGENERATE_STRUCT_NAMES_H_ +#define COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_ + +#include "compiler/translator/Intermediate.h" +#include "compiler/translator/SymbolTable.h" + +#include + +class RegenerateStructNames : public TIntermTraverser +{ + public: + RegenerateStructNames(const TSymbolTable &symbolTable, + int shaderVersion) + : mSymbolTable(symbolTable), + mShaderVersion(shaderVersion), + mScopeDepth(0) {} + + protected: + virtual void visitSymbol(TIntermSymbol *); + virtual bool visitAggregate(Visit, TIntermAggregate *); + + private: + const TSymbolTable &mSymbolTable; + int mShaderVersion; + + // Indicating the depth of the current scope. + // The global scope is 1. + int mScopeDepth; + + // If a struct's declared globally, push its ID in this set. + std::set mDeclaredGlobalStructs; +}; + +#endif // COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp index e381c32690..0cf6910aa2 100644 --- a/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp +++ b/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/RemoveTree.h" // diff --git a/src/3rdparty/angle/src/compiler/translator/RenameFunction.h b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h index 1f7fb16c45..d43e6ef7be 100644 --- a/src/3rdparty/angle/src/compiler/translator/RenameFunction.h +++ b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h @@ -7,7 +7,7 @@ #ifndef COMPILER_RENAME_FUNCTION #define COMPILER_RENAME_FUNCTION -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // // Renames a function, including its declaration and any calls to it. diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h index 39963d6a82..d87baea0fe 100644 --- a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h +++ b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h @@ -10,7 +10,7 @@ #ifndef COMPILER_REWRITE_ELSE_BLOCKS_H_ #define COMPILER_REWRITE_ELSE_BLOCKS_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" namespace sh { diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp index 3a179f7499..8857ad59bd 100644 --- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp @@ -9,6 +9,7 @@ #include +#include "angle_gl.h" #include "common/angleutils.h" namespace @@ -249,6 +250,16 @@ TString ScalarizeVecAndMatConstructorArgs::createTempVariable(TIntermTyped *orig TType type = original->getType(); type.setQualifier(EvqTemporary); + if (mShaderType == GL_FRAGMENT_SHADER && + type.getBasicType() == EbtFloat && + type.getPrecision() == EbpUndefined) + { + // We use the highest available precision for the temporary variable + // to avoid computing the actual precision using the rules defined + // in GLSL ES 1.0 Section 4.5.2. + type.setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium); + } + TIntermBinary *init = new TIntermBinary(EOpInitialize); TIntermSymbol *symbolNode = new TIntermSymbol(-1, tempVarName, type); init->setLeft(symbolNode); diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h index 6aeb0c4f60..7c6d09c1bb 100644 --- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h +++ b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h @@ -7,13 +7,16 @@ #ifndef COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ #define COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class ScalarizeVecAndMatConstructorArgs : public TIntermTraverser { public: - ScalarizeVecAndMatConstructorArgs() - : mTempVarCount(0) {} + ScalarizeVecAndMatConstructorArgs(sh::GLenum shaderType, + bool fragmentPrecisionHigh) + : mTempVarCount(0), + mShaderType(shaderType), + mFragmentPrecisionHigh(fragmentPrecisionHigh) {} protected: virtual bool visitAggregate(Visit visit, TIntermAggregate *node); @@ -36,6 +39,9 @@ class ScalarizeVecAndMatConstructorArgs : public TIntermTraverser std::vector mSequenceStack; int mTempVarCount; + + sh::GLenum mShaderType; + bool mFragmentPrecisionHigh; }; #endif // COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h index 8ddd3cb1ac..029ac30b9a 100644 --- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h +++ b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h @@ -9,7 +9,7 @@ #ifndef COMPILER_SEARCHSYMBOL_H_ #define COMPILER_SEARCHSYMBOL_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp index 6a801eacfe..20ce71605c 100644 --- a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp @@ -18,14 +18,26 @@ #include "compiler/translator/VariablePacker.h" #include "angle_gl.h" -static bool isInitialized = false; +namespace +{ + +enum ShaderVariableType +{ + SHADERVAR_UNIFORM, + SHADERVAR_VARYING, + SHADERVAR_ATTRIBUTE, + SHADERVAR_OUTPUTVARIABLE, + SHADERVAR_INTERFACEBLOCK +}; + +bool isInitialized = false; // // This is the platform independent interface between an OGL driver // and the shading language compiler. // -static bool checkVariableMaxLengths(const ShHandle handle, +static bool CheckVariableMaxLengths(const ShHandle handle, size_t expectedValue) { size_t activeUniformLimit = 0; @@ -39,7 +51,7 @@ static bool checkVariableMaxLengths(const ShHandle handle, expectedValue == varyingLimit); } -static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue) +bool CheckMappedNameMaxLength(const ShHandle handle, size_t expectedValue) { size_t mappedNameMaxLength = 0; ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength); @@ -47,7 +59,7 @@ static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue } template -static const sh::ShaderVariable *ReturnVariable(const std::vector &infoList, int index) +const sh::ShaderVariable *ReturnVariable(const std::vector &infoList, int index) { if (index < 0 || static_cast(index) >= infoList.size()) { @@ -57,7 +69,7 @@ static const sh::ShaderVariable *ReturnVariable(const std::vector &infoLis return &infoList[index]; } -static const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShaderInfo varType, int index) +const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShaderInfo varType, int index) { switch (varType) { @@ -73,7 +85,7 @@ static const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShader } } -static ShPrecisionType ConvertPrecision(sh::GLenum precision) +ShPrecisionType ConvertPrecision(sh::GLenum precision) { switch (precision) { @@ -91,6 +103,55 @@ static ShPrecisionType ConvertPrecision(sh::GLenum precision) } } +template +const std::vector *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType); + +template <> +const std::vector *GetVariableList(const TCompiler *compiler, ShaderVariableType) +{ + return &compiler->getUniforms(); +} + +template <> +const std::vector *GetVariableList(const TCompiler *compiler, ShaderVariableType) +{ + return &compiler->getVaryings(); +} + +template <> +const std::vector *GetVariableList(const TCompiler *compiler, ShaderVariableType variableType) +{ + return (variableType == SHADERVAR_ATTRIBUTE ? + &compiler->getAttributes() : + &compiler->getOutputVariables()); +} + +template <> +const std::vector *GetVariableList(const TCompiler *compiler, ShaderVariableType) +{ + return &compiler->getInterfaceBlocks(); +} + +template +const std::vector *GetShaderVariables(const ShHandle handle, ShaderVariableType variableType) +{ + if (!handle) + { + return NULL; + } + + TShHandleBase* base = static_cast(handle); + TCompiler* compiler = base->getAsCompiler(); + if (!compiler) + { + return NULL; + } + + return GetVariableList(compiler, variableType); +} + +} + // // Driver must call this first, once, before doing any other compiler operations. // Subsequent calls to this function are no-op. @@ -372,7 +433,7 @@ void ShGetVariableInfo(const ShHandle handle, // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH // in ShGetInfo, below. size_t variableLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - ASSERT(checkVariableMaxLengths(handle, variableLength)); + ASSERT(CheckVariableMaxLengths(handle, variableLength)); strncpy(name, varInfo->name.c_str(), variableLength); name[variableLength - 1] = 0; if (mappedName) @@ -380,7 +441,7 @@ void ShGetVariableInfo(const ShHandle handle, // This size must match that queried by // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. size_t maxMappedNameLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); - ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength)); + ASSERT(CheckMappedNameMaxLength(handle, maxMappedNameLength)); strncpy(mappedName, varInfo->mappedName.c_str(), maxMappedNameLength); mappedName[maxMappedNameLength - 1] = 0; } @@ -429,34 +490,29 @@ void ShGetNameHashingEntry(const ShHandle handle, hashedName[len - 1] = '\0'; } -void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params) +const std::vector *ShGetUniforms(const ShHandle handle) { - if (!handle || !params) - return; + return GetShaderVariables(handle, SHADERVAR_UNIFORM); +} - TShHandleBase* base = static_cast(handle); - TranslatorHLSL* translator = base->getAsTranslatorHLSL(); - if (!translator) return; +const std::vector *ShGetVaryings(const ShHandle handle) +{ + return GetShaderVariables(handle, SHADERVAR_VARYING); +} - switch(pname) - { - case SH_ACTIVE_UNIFORMS_ARRAY: - *params = (void*)&translator->getUniforms(); - break; - case SH_ACTIVE_INTERFACE_BLOCKS_ARRAY: - *params = (void*)&translator->getInterfaceBlocks(); - break; - case SH_ACTIVE_OUTPUT_VARIABLES_ARRAY: - *params = (void*)&translator->getOutputVariables(); - break; - case SH_ACTIVE_ATTRIBUTES_ARRAY: - *params = (void*)&translator->getAttributes(); - break; - case SH_ACTIVE_VARYINGS_ARRAY: - *params = (void*)&translator->getVaryings(); - break; - default: UNREACHABLE(); - } +const std::vector *ShGetAttributes(const ShHandle handle) +{ + return GetShaderVariables(handle, SHADERVAR_ATTRIBUTE); +} + +const std::vector *ShGetOutputVariables(const ShHandle handle) +{ + return GetShaderVariables(handle, SHADERVAR_OUTPUTVARIABLE); +} + +const std::vector *ShGetInterfaceBlocks(const ShHandle handle) +{ + return GetShaderVariables(handle, SHADERVAR_INTERFACEBLOCK); } int ShCheckVariablesWithinPackingLimits( @@ -468,7 +524,7 @@ int ShCheckVariablesWithinPackingLimits( std::vector variables; for (size_t ii = 0; ii < varInfoArraySize; ++ii) { - sh::ShaderVariable var(varInfoArray[ii].type, (sh::GLenum)0, "", varInfoArray[ii].size); + sh::ShaderVariable var(varInfoArray[ii].type, varInfoArray[ii].size); variables.push_back(var); } VariablePacker packer; diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp new file mode 100644 index 0000000000..822c558c9b --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp @@ -0,0 +1,166 @@ +// +// 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. +// +// ShaderVars.cpp: +// Methods for GL variable types (varyings, uniforms, etc) +// + +#include + +namespace sh +{ + +ShaderVariable::ShaderVariable() + : type(0), + precision(0), + arraySize(0), + staticUse(false) +{} + +ShaderVariable::ShaderVariable(GLenum typeIn, unsigned int arraySizeIn) + : type(typeIn), + precision(0), + arraySize(arraySizeIn), + staticUse(false) +{} + +ShaderVariable::~ShaderVariable() +{} + +ShaderVariable::ShaderVariable(const ShaderVariable &other) + : type(other.type), + precision(other.precision), + name(other.name), + mappedName(other.mappedName), + arraySize(other.arraySize), + staticUse(other.staticUse), + fields(other.fields), + structName(other.structName) +{} + +ShaderVariable &ShaderVariable::operator=(const ShaderVariable &other) +{ + type = other.type; + precision = other.precision; + name = other.name; + mappedName = other.mappedName; + arraySize = other.arraySize; + staticUse = other.staticUse; + fields = other.fields; + structName = other.structName; + return *this; +} + +Uniform::Uniform() +{} + +Uniform::~Uniform() +{} + +Uniform::Uniform(const Uniform &other) + : ShaderVariable(other) +{} + +Uniform &Uniform::operator=(const Uniform &other) +{ + ShaderVariable::operator=(other); + return *this; +} + +Attribute::Attribute() + : location(-1) +{} + +Attribute::~Attribute() +{} + +Attribute::Attribute(const Attribute &other) + : ShaderVariable(other), + location(other.location) +{} + +Attribute &Attribute::operator=(const Attribute &other) +{ + ShaderVariable::operator=(other); + location = other.location; + return *this; +} + +InterfaceBlockField::InterfaceBlockField() + : isRowMajorLayout(false) +{} + +InterfaceBlockField::~InterfaceBlockField() +{} + +InterfaceBlockField::InterfaceBlockField(const InterfaceBlockField &other) + : ShaderVariable(other), + isRowMajorLayout(other.isRowMajorLayout) +{} + +InterfaceBlockField &InterfaceBlockField::operator=(const InterfaceBlockField &other) +{ + ShaderVariable::operator=(other); + isRowMajorLayout = other.isRowMajorLayout; + return *this; +} + +Varying::Varying() + : interpolation(INTERPOLATION_SMOOTH), + isInvariant(false) +{} + +Varying::~Varying() +{} + +Varying::Varying(const Varying &other) + : ShaderVariable(other), + interpolation(other.interpolation), + isInvariant(other.isInvariant) +{} + +Varying &Varying::operator=(const Varying &other) +{ + ShaderVariable::operator=(other); + interpolation = other.interpolation; + isInvariant = other.isInvariant; + return *this; +} + +InterfaceBlock::InterfaceBlock() + : arraySize(0), + layout(BLOCKLAYOUT_PACKED), + isRowMajorLayout(false), + staticUse(false) +{} + +InterfaceBlock::~InterfaceBlock() +{} + +InterfaceBlock::InterfaceBlock(const InterfaceBlock &other) + : name(other.name), + mappedName(other.mappedName), + instanceName(other.instanceName), + arraySize(other.arraySize), + layout(other.layout), + isRowMajorLayout(other.isRowMajorLayout), + staticUse(other.staticUse), + fields(other.fields) +{} + +InterfaceBlock &InterfaceBlock::operator=(const InterfaceBlock &other) +{ + name = other.name; + mappedName = other.mappedName; + instanceName = other.instanceName; + arraySize = other.arraySize; + layout = other.layout; + isRowMajorLayout = other.isRowMajorLayout; + staticUse = other.staticUse; + fields = other.fields; + return *this; +} + +} diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp index 365985c852..48929affe6 100644 --- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp @@ -17,12 +17,19 @@ namespace sh { -Std140PaddingHelper::Std140PaddingHelper(const std::map &structElementIndexes) - : mPaddingCounter(0), +Std140PaddingHelper::Std140PaddingHelper(const std::map &structElementIndexes, + unsigned *uniqueCounter) + : mPaddingCounter(uniqueCounter), mElementIndex(0), mStructElementIndexes(structElementIndexes) {} +TString Std140PaddingHelper::next() +{ + unsigned value = (*mPaddingCounter)++; + return str(value); +} + int Std140PaddingHelper::prePadding(const TType &type) { if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray()) @@ -68,7 +75,7 @@ TString Std140PaddingHelper::prePaddingString(const TType &type) for (int paddingIndex = 0; paddingIndex < paddingCount; paddingIndex++) { - padding += " float pad_" + str(mPaddingCounter++) + ";\n"; + padding += " float pad_" + next() + ";\n"; } return padding; @@ -116,19 +123,25 @@ TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRo TString padding; for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++) { - padding += " float pad_" + str(mPaddingCounter++) + ";\n"; + padding += " float pad_" + next() + ";\n"; } return padding; } StructureHLSL::StructureHLSL() + : mUniquePaddingCounter(0) {} +Std140PaddingHelper StructureHLSL::getPaddingHelper() +{ + return Std140PaddingHelper(mStd140StructElementIndexes, &mUniquePaddingCounter); +} + TString StructureHLSL::defineQualified(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing) { if (useStd140Packing) { - Std140PaddingHelper padHelper(mStd140StructElementIndexes); + Std140PaddingHelper padHelper = getPaddingHelper(); return define(structure, useHLSLRowMajorPacking, useStd140Packing, &padHelper); } else @@ -291,9 +304,9 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const if (parameter.isScalar()) { - for (int row = 0; row < rows; row++) + for (int col = 0; col < cols; col++) { - for (int col = 0; col < cols; col++) + for (int row = 0; row < rows; row++) { constructor += TString((row == col) ? "x0" : "0.0"); @@ -306,13 +319,13 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const } else if (parameter.isMatrix()) { - for (int row = 0; row < rows; row++) + for (int col = 0; col < cols; col++) { - for (int col = 0; col < cols; col++) + for (int row = 0; row < rows; row++) { if (row < parameter.getRows() && col < parameter.getCols()) { - constructor += TString("x0") + "[" + str(row) + "][" + str(col) + "]"; + constructor += TString("x0") + "[" + str(col) + "][" + str(row) + "]"; } else { @@ -461,7 +474,7 @@ std::string StructureHLSL::structsHeader() const void StructureHLSL::storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking) { - Std140PaddingHelper padHelper(mStd140StructElementIndexes); + Std140PaddingHelper padHelper = getPaddingHelper(); const TFieldList &fields = structure.fields(); for (unsigned int i = 0; i < fields.size(); i++) diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h index 63fbaaaf8e..ed002fef30 100644 --- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h @@ -11,7 +11,7 @@ #define TRANSLATOR_STRUCTUREHLSL_H_ #include "compiler/translator/Common.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include @@ -26,7 +26,8 @@ namespace sh class Std140PaddingHelper { public: - explicit Std140PaddingHelper(const std::map &structElementIndexes); + explicit Std140PaddingHelper(const std::map &structElementIndexes, + unsigned *uniqueCounter); int elementIndex() const { return mElementIndex; } int prePadding(const TType &type); @@ -34,7 +35,9 @@ class Std140PaddingHelper TString postPaddingString(const TType &type, bool useHLSLRowMajorPacking); private: - int mPaddingCounter; + TString next(); + + unsigned *mPaddingCounter; int mElementIndex; const std::map &mStructElementIndexes; }; @@ -50,9 +53,11 @@ class StructureHLSL TString defineQualified(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing); static TString defineNameless(const TStructure &structure); - Std140PaddingHelper getPaddingHelper() const { return Std140PaddingHelper(mStd140StructElementIndexes); } + Std140PaddingHelper getPaddingHelper(); private: + unsigned mUniquePaddingCounter; + std::map mStd140StructElementIndexes; typedef std::set StructNames; diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp index ae4fcaa6c3..028da21151 100644 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp @@ -98,7 +98,8 @@ TSymbol::TSymbol(const TSymbol ©Of) uniqueId = copyOf.uniqueId; } -TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope) +TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, + bool *builtIn, bool *sameScope) const { int level = currentLevel(); TSymbol *symbol; @@ -122,7 +123,8 @@ TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtI return symbol; } -TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) +TSymbol *TSymbolTable::findBuiltIn( + const TString &name, int shaderVersion) const { for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--) { @@ -210,7 +212,7 @@ void TSymbolTable::insertBuiltIn( insert(level, function); } -TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) +TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const { if (!SupportsPrecision(type)) return EbpUndefined; diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h index d3ddf19e34..6b0e0c0a03 100644 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h @@ -34,7 +34,7 @@ #include "common/angleutils.h" #include "compiler/translator/InfoSink.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // Symbol base class. (Can build functions or variables out of these...) class TSymbol @@ -323,15 +323,15 @@ class TSymbolTable // When the symbol table is initialized with the built-ins, there should // 'push' calls, so that built-ins are at level 0 and the shader // globals are at level 1. - bool isEmpty() + bool isEmpty() const { return table.empty(); } - bool atBuiltInLevel() + bool atBuiltInLevel() const { return currentLevel() <= LAST_BUILTIN_LEVEL; } - bool atGlobalLevel() + bool atGlobalLevel() const { return currentLevel() <= GLOBAL_LEVEL; } @@ -373,8 +373,8 @@ class TSymbolTable TType *ptype4 = 0, TType *ptype5 = 0); TSymbol *find(const TString &name, int shaderVersion, - bool *builtIn = NULL, bool *sameScope = NULL); - TSymbol *findBuiltIn(const TString &name, int shaderVersion); + bool *builtIn = NULL, bool *sameScope = NULL) const; + TSymbol *findBuiltIn(const TString &name, int shaderVersion) const; TSymbolTableLevel *getOuterLevel() { @@ -406,7 +406,7 @@ class TSymbolTable // Searches down the precisionStack for a precision qualifier // for the specified TBasicType - TPrecision getDefaultPrecision(TBasicType type); + TPrecision getDefaultPrecision(TBasicType type) const; static int nextUniqueId() { diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp index 52588e4626..22bf60e86e 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp @@ -17,16 +17,10 @@ TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutpu void TranslatorHLSL::translate(TIntermNode *root) { TParseContext& parseContext = *GetGlobalParseContext(); - sh::OutputHLSL outputHLSL(parseContext, getResources(), getOutputType()); + sh::OutputHLSL outputHLSL(parseContext, this); outputHLSL.output(); - attributes = outputHLSL.getAttributes(); - outputVariables = outputHLSL.getOutputVariables(); - uniforms = outputHLSL.getUniforms(); - varyings = outputHLSL.getVaryings(); - interfaceBlocks = outputHLSL.getInterfaceBlocks(); - 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 598c8a7b30..11a042d83a 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h @@ -8,7 +8,6 @@ #define COMPILER_TRANSLATORHLSL_H_ #include "compiler/translator/Compiler.h" -#include "common/shadervars.h" class TranslatorHLSL : public TCompiler { diff --git a/src/3rdparty/angle/src/compiler/translator/Types.cpp b/src/3rdparty/angle/src/compiler/translator/Types.cpp index bafad0d64f..d36936fb23 100644 --- a/src/3rdparty/angle/src/compiler/translator/Types.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Types.cpp @@ -13,6 +13,38 @@ #include #include +const char* getBasicString(TBasicType t) +{ + switch (t) + { + case EbtVoid: return "void"; break; + case EbtFloat: return "float"; break; + case EbtInt: return "int"; break; + case EbtUInt: return "uint"; break; + case EbtBool: return "bool"; break; + case EbtSampler2D: return "sampler2D"; break; + case EbtSampler3D: return "sampler3D"; break; + case EbtSamplerCube: return "samplerCube"; break; + case EbtSamplerExternalOES: return "samplerExternalOES"; break; + case EbtSampler2DRect: return "sampler2DRect"; break; + case EbtSampler2DArray: return "sampler2DArray"; break; + case EbtISampler2D: return "isampler2D"; break; + case EbtISampler3D: return "isampler3D"; break; + case EbtISamplerCube: return "isamplerCube"; break; + case EbtISampler2DArray: return "isampler2DArray"; break; + case EbtUSampler2D: return "usampler2D"; break; + case EbtUSampler3D: return "usampler3D"; break; + case EbtUSamplerCube: return "usamplerCube"; break; + case EbtUSampler2DArray: return "usampler2DArray"; break; + case EbtSampler2DShadow: return "sampler2DShadow"; break; + case EbtSamplerCubeShadow: return "samplerCubeShadow"; break; + case EbtSampler2DArrayShadow: return "sampler2DArrayShadow"; break; + case EbtStruct: return "structure"; break; + case EbtInterfaceBlock: return "interface block"; break; + default: UNREACHABLE(); return "unknown type"; + } +} + TType::TType(const TPublicType &p) : type(p.type), precision(p.precision), qualifier(p.qualifier), layoutQualifier(p.layoutQualifier), primarySize(p.primarySize), secondarySize(p.secondarySize), array(p.array), arraySize(p.arraySize), diff --git a/src/3rdparty/angle/src/compiler/translator/Types.h b/src/3rdparty/angle/src/compiler/translator/Types.h index bc50a4dc64..075196daa3 100644 --- a/src/3rdparty/angle/src/compiler/translator/Types.h +++ b/src/3rdparty/angle/src/compiler/translator/Types.h @@ -140,6 +140,17 @@ class TStructure : public TFieldListCollection private: DISALLOW_COPY_AND_ASSIGN(TStructure); + + // 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. + friend class RegenerateStructNames; + void setName(const TString &name) + { + TString *mutableName = const_cast(mName); + *mutableName = name; + } + virtual TString mangledNamePrefix() const { return "struct-"; diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h index 1e416bc04c..6fd3b457bd 100644 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h @@ -9,7 +9,7 @@ #ifndef COMPILER_UNFOLDSHORTCIRCUIT_H_ #define COMPILER_UNFOLDSHORTCIRCUIT_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/ParseContext.h" namespace sh diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h index 24c14a60e3..3acaf7ee7c 100644 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h @@ -11,7 +11,7 @@ #define COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_ #include "common/angleutils.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // This traverser identifies all the short circuit binary nodes that need to // be replaced, and creates the corresponding replacement nodes. However, diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp index 41a7d2c10b..61b6ed7455 100644 --- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp @@ -14,6 +14,7 @@ #include "compiler/translator/StructureHLSL.h" #include "compiler/translator/util.h" #include "compiler/translator/UtilsHLSL.h" +#include "compiler/translator/TranslatorHLSL.h" namespace sh { @@ -30,18 +31,6 @@ static const char *UniformRegisterPrefix(const TType &type) } } -static TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field) -{ - if (interfaceBlock.hasInstanceName()) - { - return interfaceBlock.name() + "." + field.name(); - } - else - { - return field.name(); - } -} - static TString InterfaceBlockFieldTypeString(const TField &field, TLayoutBlockStorage blockStorage) { const TType &fieldType = *field.type(); @@ -72,12 +61,13 @@ static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock) return DecoratePrivate(interfaceBlock.name()) + "_type"; } -UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType) +UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator) : mUniformRegister(0), mInterfaceBlockRegister(0), mSamplerRegister(0), mStructureHLSL(structureHLSL), - mOutputType(outputType) + mOutputType(translator->getOutputType()), + mUniforms(translator->getUniforms()) {} void UniformHLSL::reserveUniformRegisters(unsigned int registerCount) @@ -90,18 +80,32 @@ void UniformHLSL::reserveInterfaceBlockRegisters(unsigned int registerCount) mInterfaceBlockRegister = registerCount; } +const Uniform *UniformHLSL::findUniformByName(const TString &name) const +{ + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex) + { + if (mUniforms[uniformIndex].name == name.c_str()) + { + return &mUniforms[uniformIndex]; + } + } + + UNREACHABLE(); + return NULL; +} + unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, const TString &name) { unsigned int registerIndex = (IsSampler(type.getBasicType()) ? mSamplerRegister : mUniformRegister); - GetVariableTraverser traverser(&mActiveUniforms); - traverser.traverse(type, name); + const Uniform *uniform = findUniformByName(name); + ASSERT(uniform); - const sh::Uniform &activeUniform = mActiveUniforms.back(); - mUniformRegisterMap[activeUniform.name] = registerIndex; + mUniformRegisterMap[uniform->name] = registerIndex; - unsigned int registerCount = HLSLVariableRegisterCount(activeUniform, mOutputType); - if (IsSampler(type.getBasicType())) + unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType); + + if (gl::IsSampler(uniform->type)) { mSamplerRegister += registerCount; } @@ -137,7 +141,12 @@ TString UniformHLSL::uniformsHeader(ShShaderOutput outputType, const ReferencedS else { const TStructure *structure = type.getStruct(); - const TString &typeName = (structure ? QualifiedStructNameString(*structure, false, false) : TypeString(type)); + // If this is a nameless struct, we need to use its full definition, rather than its (empty) name. + // TypeString() will invoke defineNameless in this case; qualifier prefixes are unnecessary for + // nameless structs in ES, as nameless structs cannot be used anywhere that layout qualifiers are + // permitted. + const TString &typeName = ((structure && !structure->name().empty()) ? + QualifiedStructNameString(*structure, false, false) : TypeString(type)); const TString ®isterString = TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")"; @@ -157,33 +166,14 @@ TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedIn { const TType &nodeType = interfaceBlockIt->second->getType(); const TInterfaceBlock &interfaceBlock = *nodeType.getInterfaceBlock(); - const TFieldList &fieldList = interfaceBlock.fields(); unsigned int arraySize = static_cast(interfaceBlock.arraySize()); unsigned int activeRegister = mInterfaceBlockRegister; - InterfaceBlock activeBlock(interfaceBlock.name().c_str(), arraySize); - for (unsigned int typeIndex = 0; typeIndex < fieldList.size(); typeIndex++) - { - const TField &field = *fieldList[typeIndex]; - const TString &fullFieldName = InterfaceBlockFieldName(interfaceBlock, field); - - bool isRowMajor = (field.type()->getLayoutQualifier().matrixPacking == EmpRowMajor); - GetInterfaceBlockFieldTraverser traverser(&activeBlock.fields, isRowMajor); - traverser.traverse(*field.type(), fullFieldName); - } - - mInterfaceBlockRegisterMap[activeBlock.name] = activeRegister; + mInterfaceBlockRegisterMap[interfaceBlock.name().c_str()] = activeRegister; mInterfaceBlockRegister += std::max(1u, arraySize); - activeBlock.layout = GetBlockLayoutType(interfaceBlock.blockStorage()); - - if (interfaceBlock.matrixPacking() == EmpRowMajor) - { - activeBlock.isRowMajorLayout = true; - } - - mActiveInterfaceBlocks.push_back(activeBlock); + // FIXME: interface block field names if (interfaceBlock.hasInstanceName()) { @@ -261,7 +251,7 @@ TString UniformHLSL::interfaceBlockMembersString(const TInterfaceBlock &interfac if (blockStorage == EbsStd140) { // 2 and 3 component vector types in some cases need pre-padding - hlsl += padHelper.prePadding(fieldType); + hlsl += padHelper.prePaddingString(fieldType); } hlsl += " " + InterfaceBlockFieldTypeString(field, blockStorage) + diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h index 835b1ef2c8..91fa51588b 100644 --- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h @@ -10,7 +10,6 @@ #ifndef TRANSLATOR_UNIFORMHLSL_H_ #define TRANSLATOR_UNIFORMHLSL_H_ -#include "common/shadervars.h" #include "compiler/translator/Types.h" namespace sh @@ -20,7 +19,7 @@ class StructureHLSL; class UniformHLSL { public: - UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType); + UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator); void reserveUniformRegisters(unsigned int registerCount); void reserveInterfaceBlockRegisters(unsigned int registerCount); @@ -30,8 +29,6 @@ class UniformHLSL // Used for direct index references static TString interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex); - const std::vector &getUniforms() const { return mActiveUniforms; } - const std::vector &getInterfaceBlocks() const { return mActiveInterfaceBlocks; } const std::map &getInterfaceBlockRegisterMap() const { return mInterfaceBlockRegisterMap; @@ -45,6 +42,7 @@ class UniformHLSL TString interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex); TString interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage); TString interfaceBlockStructString(const TInterfaceBlock &interfaceBlock); + const Uniform *findUniformByName(const TString &name) const; // Returns the uniform's register index unsigned int declareUniformAndAssignRegister(const TType &type, const TString &name); @@ -55,8 +53,7 @@ class UniformHLSL StructureHLSL *mStructureHLSL; ShShaderOutput mOutputType; - std::vector mActiveUniforms; - std::vector mActiveInterfaceBlocks; + const std::vector &mUniforms; std::map mInterfaceBlockRegisterMap; std::map mUniformRegisterMap; }; diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h index 8c9ebf53ed..e6e8a9619f 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h +++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/LoopInfo.h" class TInfoSinkBase; diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h index e391ad9486..0f808dbb97 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h +++ b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp index 153455c4f1..f26c1566ac 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp @@ -9,20 +9,46 @@ #include "compiler/translator/util.h" #include "common/utilities.h" -template -static void ExpandUserDefinedVariable(const VarT &variable, - const std::string &name, - const std::string &mappedName, - bool markStaticUse, - std::vector *expanded); +namespace sh +{ -// Returns info for an attribute, uniform, or varying. -template -static void ExpandVariable(const VarT &variable, - const std::string &name, - const std::string &mappedName, - bool markStaticUse, - std::vector *expanded) +namespace +{ + +TString InterfaceBlockFieldName(const TInterfaceBlock &interfaceBlock, const TField &field) +{ + if (interfaceBlock.hasInstanceName()) + { + return interfaceBlock.name() + "." + field.name(); + } + else + { + return field.name(); + } +} + +BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage) +{ + switch (blockStorage) + { + case EbsPacked: return BLOCKLAYOUT_PACKED; + case EbsShared: return BLOCKLAYOUT_SHARED; + case EbsStd140: return BLOCKLAYOUT_STANDARD; + default: UNREACHABLE(); return BLOCKLAYOUT_SHARED; + } +} + +void ExpandUserDefinedVariable(const ShaderVariable &variable, + const std::string &name, + const std::string &mappedName, + bool markStaticUse, + std::vector *expanded); + +void ExpandVariable(const ShaderVariable &variable, + const std::string &name, + const std::string &mappedName, + bool markStaticUse, + std::vector *expanded) { if (variable.isStruct()) { @@ -30,8 +56,8 @@ static void ExpandVariable(const VarT &variable, { for (size_t elementIndex = 0; elementIndex < variable.elementCount(); elementIndex++) { - std::string lname = name + ArrayString(elementIndex); - std::string lmappedName = mappedName + ArrayString(elementIndex); + std::string lname = name + ::ArrayString(elementIndex); + std::string lmappedName = mappedName + ::ArrayString(elementIndex); ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded); } } @@ -42,7 +68,7 @@ static void ExpandVariable(const VarT &variable, } else { - VarT expandedVar = variable; + ShaderVariable expandedVar = variable; expandedVar.name = name; expandedVar.mappedName = mappedName; @@ -63,20 +89,19 @@ static void ExpandVariable(const VarT &variable, } } -template -static void ExpandUserDefinedVariable(const VarT &variable, - const std::string &name, - const std::string &mappedName, - bool markStaticUse, - std::vector *expanded) +void ExpandUserDefinedVariable(const ShaderVariable &variable, + const std::string &name, + const std::string &mappedName, + bool markStaticUse, + std::vector *expanded) { ASSERT(variable.isStruct()); - const std::vector &fields = variable.fields; + const std::vector &fields = variable.fields; for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) { - const VarT &field = fields[fieldIndex]; + const ShaderVariable &field = fields[fieldIndex]; ExpandVariable(field, name + "." + field.name, mappedName + "." + field.mappedName, @@ -86,8 +111,8 @@ static void ExpandUserDefinedVariable(const VarT &variable, } template -static VarT *FindVariable(const TString &name, - std::vector *infoList) +VarT *FindVariable(const TString &name, + std::vector *infoList) { // TODO(zmo): optimize this function. for (size_t ii = 0; ii < infoList->size(); ++ii) @@ -99,6 +124,8 @@ static VarT *FindVariable(const TString &name, return NULL; } +} + CollectVariables::CollectVariables(std::vector *attribs, std::vector *outputVariables, std::vector *uniforms, @@ -125,14 +152,18 @@ CollectVariables::CollectVariables(std::vector *attribs, void CollectVariables::visitSymbol(TIntermSymbol *symbol) { ASSERT(symbol != NULL); - sh::ShaderVariable *var = NULL; + ShaderVariable *var = NULL; const TString &symbolName = symbol->getSymbol(); - if (sh::IsVarying(symbol->getQualifier())) + if (IsVarying(symbol->getQualifier())) { var = FindVariable(symbolName, mVaryings); } - else if (symbol->getType() != EbtInterfaceBlock) + else if (symbol->getType().getBasicType() == EbtInterfaceBlock) + { + UNREACHABLE(); + } + else { switch (symbol->getQualifier()) { @@ -148,12 +179,13 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock(); if (interfaceBlock) { - sh::InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks); + InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks); ASSERT(namedBlock); var = FindVariable(symbolName, &namedBlock->fields); // Set static use on the parent interface block here namedBlock->staticUse = true; + } else { @@ -167,7 +199,7 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) case EvqFragCoord: if (!mFragCoordAdded) { - sh::Varying info; + Varying info; info.name = "gl_FragCoord"; info.mappedName = "gl_FragCoord"; info.type = GL_FLOAT_VEC4; @@ -181,7 +213,7 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) case EvqFrontFacing: if (!mFrontFacingAdded) { - sh::Varying info; + Varying info; info.name = "gl_FrontFacing"; info.mappedName = "gl_FrontFacing"; info.type = GL_BOOL; @@ -195,7 +227,7 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) case EvqPointCoord: if (!mPointCoordAdded) { - sh::Varying info; + Varying info; info.name = "gl_PointCoord"; info.mappedName = "gl_PointCoord"; info.type = GL_FLOAT_VEC2; @@ -216,17 +248,17 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol) } } -template -class NameHashingTraverser : public sh::GetVariableTraverser +class NameHashingTraverser : public GetVariableTraverser { public: - NameHashingTraverser(std::vector *output, ShHashFunction64 hashFunction) - : sh::GetVariableTraverser(output), - mHashFunction(hashFunction) + NameHashingTraverser(ShHashFunction64 hashFunction) + : mHashFunction(hashFunction) {} private: - void visitVariable(VarT *variable) + DISALLOW_COPY_AND_ASSIGN(NameHashingTraverser); + + virtual void visitVariable(ShaderVariable *variable) { TString stringName = TString(variable->name.c_str()); variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str(); @@ -238,16 +270,16 @@ class NameHashingTraverser : public sh::GetVariableTraverser // Attributes, which cannot have struct fields, are a special case template <> void CollectVariables::visitVariable(const TIntermSymbol *variable, - std::vector *infoList) const + std::vector *infoList) const { ASSERT(variable); const TType &type = variable->getType(); ASSERT(!type.getStruct()); - sh::Attribute attribute; + Attribute attribute; - attribute.type = sh::GLVariableType(type); - attribute.precision = sh::GLVariablePrecision(type); + attribute.type = GLVariableType(type); + attribute.precision = GLVariablePrecision(type); attribute.name = variable->getSymbol().c_str(); attribute.arraySize = static_cast(type.getArraySize()); attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str(); @@ -258,29 +290,32 @@ void CollectVariables::visitVariable(const TIntermSymbol *variable, template <> void CollectVariables::visitVariable(const TIntermSymbol *variable, - std::vector *infoList) const + std::vector *infoList) const { - sh::InterfaceBlock interfaceBlock; + InterfaceBlock interfaceBlock; const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock(); - - bool isRowMajor = (blockType->matrixPacking() == EmpRowMajor); + ASSERT(blockType); interfaceBlock.name = blockType->name().c_str(); interfaceBlock.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str(); + interfaceBlock.instanceName = (blockType->hasInstanceName() ? blockType->instanceName().c_str() : ""); interfaceBlock.arraySize = variable->getArraySize(); - interfaceBlock.isRowMajorLayout = isRowMajor; - interfaceBlock.layout = sh::GetBlockLayoutType(blockType->blockStorage()); + interfaceBlock.isRowMajorLayout = (blockType->matrixPacking() == EmpRowMajor); + interfaceBlock.layout = GetBlockLayoutType(blockType->blockStorage()); - ASSERT(blockType); - const TFieldList &blockFields = blockType->fields(); + // Gather field information + const TFieldList &fieldList = blockType->fields(); - for (size_t fieldIndex = 0; fieldIndex < blockFields.size(); fieldIndex++) + for (size_t fieldIndex = 0; fieldIndex < fieldList.size(); ++fieldIndex) { - const TField *field = blockFields[fieldIndex]; - ASSERT(field); + const TField &field = *fieldList[fieldIndex]; + const TString &fullFieldName = InterfaceBlockFieldName(*blockType, field); + const TType &fieldType = *field.type(); - sh::GetInterfaceBlockFieldTraverser traverser(&interfaceBlock.fields, isRowMajor); - traverser.traverse(*field->type(), field->name()); + GetVariableTraverser traverser; + traverser.traverse(fieldType, fullFieldName, &interfaceBlock.fields); + + interfaceBlock.fields.back().isRowMajorLayout = (fieldType.getLayoutQualifier().matrixPacking == EmpRowMajor); } infoList->push_back(interfaceBlock); @@ -290,8 +325,8 @@ template void CollectVariables::visitVariable(const TIntermSymbol *variable, std::vector *infoList) const { - NameHashingTraverser traverser(infoList, mHashFunction); - traverser.traverse(variable->getType(), variable->getSymbol()); + NameHashingTraverser traverser(mHashFunction); + traverser.traverse(variable->getType(), variable->getSymbol(), infoList); } template @@ -320,16 +355,19 @@ bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node) case EOpDeclaration: { const TIntermSequence &sequence = *(node->getSequence()); + ASSERT(!sequence.empty()); + const TIntermTyped &typedNode = *(sequence.front()->getAsTyped()); TQualifier qualifier = typedNode.getQualifier(); if (typedNode.getBasicType() == EbtInterfaceBlock) { visitInfoList(sequence, mInterfaceBlocks); + visitChildren = false; } else if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqFragmentOut || qualifier == EvqUniform || - sh::IsVarying(qualifier)) + IsVarying(qualifier)) { switch (qualifier) { @@ -348,10 +386,7 @@ bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node) break; } - if (!sequence.empty()) - { - visitChildren = false; - } + visitChildren = false; } break; } @@ -361,15 +396,43 @@ bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node) return visitChildren; } +bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode) +{ + if (binaryNode->getOp() == EOpIndexDirectInterfaceBlock) + { + // NOTE: we do not determine static use for individual blocks of an array + TIntermTyped *blockNode = binaryNode->getLeft()->getAsTyped(); + ASSERT(blockNode); + + TIntermConstantUnion *constantUnion = binaryNode->getRight()->getAsConstantUnion(); + ASSERT(constantUnion); + + const TInterfaceBlock *interfaceBlock = blockNode->getType().getInterfaceBlock(); + InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks); + ASSERT(namedBlock); + namedBlock->staticUse = true; + + unsigned int fieldIndex = constantUnion->getUConst(0); + ASSERT(fieldIndex < namedBlock->fields.size()); + namedBlock->fields[fieldIndex].staticUse = true; + return false; + } + + return true; +} + template -void ExpandVariables(const std::vector &compact, std::vector *expanded) +void ExpandVariables(const std::vector &compact, + std::vector *expanded) { for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++) { - const VarT &variable = compact[variableIndex]; + const ShaderVariable &variable = compact[variableIndex]; ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded); } } -template void ExpandVariables(const std::vector &, std::vector *); -template void ExpandVariables(const std::vector &, std::vector *); +template void ExpandVariables(const std::vector &, std::vector *); +template void ExpandVariables(const std::vector &, std::vector *); + +} diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h index 3771819c8b..5ac4c46baa 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h @@ -7,22 +7,27 @@ #ifndef COMPILER_VARIABLE_INFO_H_ #define COMPILER_VARIABLE_INFO_H_ -#include "compiler/translator/intermediate.h" -#include "common/shadervars.h" +#include + +#include "compiler/translator/IntermNode.h" + +namespace sh +{ // Traverses intermediate tree to collect all attributes, uniforms, varyings. class CollectVariables : public TIntermTraverser { public: - CollectVariables(std::vector *attribs, - std::vector *outputVariables, - std::vector *uniforms, - std::vector *varyings, - std::vector *interfaceBlocks, + CollectVariables(std::vector *attribs, + std::vector *outputVariables, + std::vector *uniforms, + std::vector *varyings, + std::vector *interfaceBlocks, ShHashFunction64 hashFunction); virtual void visitSymbol(TIntermSymbol *symbol); virtual bool visitAggregate(Visit, TIntermAggregate *node); + virtual bool visitBinary(Visit visit, TIntermBinary *binaryNode); private: template @@ -31,13 +36,13 @@ class CollectVariables : public TIntermTraverser template void visitInfoList(const TIntermSequence &sequence, std::vector *infoList) const; - std::vector *mAttribs; - std::vector *mOutputVariables; - std::vector *mUniforms; - std::vector *mVaryings; - std::vector *mInterfaceBlocks; + std::vector *mAttribs; + std::vector *mOutputVariables; + std::vector *mUniforms; + std::vector *mVaryings; + std::vector *mInterfaceBlocks; - std::map mInterfaceBlockFields; + std::map mInterfaceBlockFields; bool mPointCoordAdded; bool mFrontFacingAdded; @@ -47,8 +52,10 @@ class CollectVariables : public TIntermTraverser }; // Expand struct variables to flattened lists of split variables -// Implemented for sh::Varying and sh::Uniform. template -void ExpandVariables(const std::vector &compact, std::vector *expanded); +void ExpandVariables(const std::vector &compact, + std::vector *expanded); + +} #endif // COMPILER_VARIABLE_INFO_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp b/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp index faaf0115fc..e69052162a 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp @@ -3,12 +3,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -#include "compiler/translator/VariablePacker.h" -#include "angle_gl.h" -#include "common/utilities.h" #include +#include "angle_gl.h" + +#include "compiler/translator/VariablePacker.h" +#include "common/utilities.h" + int VariablePacker::GetNumComponentsPerRow(sh::GLenum type) { switch (type) diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp index 12dc9e0dad..8edbd009b0 100644 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp @@ -67,6 +67,9 @@ bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node) } break; } + case EOpInvariantDeclaration: + updateVersion(GLSL_VERSION_120); + break; case EOpParameters: { const TIntermSequence ¶ms = *(node->getSequence()); diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h index de4141d38c..30f5a138a0 100644 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TRANSLATOR_VERSIONGLSL_H_ #define COMPILER_TRANSLATOR_VERSIONGLSL_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" // Traverses the intermediate tree to return the minimum GLSL version // required to legally access all built-in features used in the shader. diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h index 5ea1cbb837..bc25fe7cbc 100644 --- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h @@ -7,7 +7,7 @@ #ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H #define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include #include diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.y b/src/3rdparty/angle/src/compiler/translator/glslang.y index fb2d835368..5c945ad5ad 100644 --- a/src/3rdparty/angle/src/compiler/translator/glslang.y +++ b/src/3rdparty/angle/src/compiler/translator/glslang.y @@ -209,38 +209,7 @@ identifier variable_identifier : IDENTIFIER { // The symbol table search was done in the lexical phase - const TSymbol *symbol = $1.symbol; - const TVariable *variable = 0; - - if (!symbol) - { - context->error(@1, "undeclared identifier", $1.string->c_str()); - context->recover(); - } - else if (!symbol->isVariable()) - { - context->error(@1, "variable expected", $1.string->c_str()); - context->recover(); - } - else - { - variable = static_cast(symbol); - - if (context->symbolTable.findBuiltIn(variable->getName(), context->shaderVersion) && - !variable->getExtension().empty() && - context->extensionErrorCheck(@1, variable->getExtension())) - { - context->recover(); - } - } - - if (!variable) - { - TType type(EbtFloat, EbpUndefined); - TVariable *fakeVariable = new TVariable($1.string, type); - context->symbolTable.declare(fakeVariable); - variable = fakeVariable; - } + const TVariable *variable = context->getNamedVariable(@1, $1.string, $1.symbol); if (variable->getType().getQualifier() == EvqConst) { @@ -816,9 +785,10 @@ declaration context->symbolTable.pop(); } | init_declarator_list SEMICOLON { - if ($1.intermAggregate) - $1.intermAggregate->setOp(EOpDeclaration); - $$ = $1.intermAggregate; + TIntermAggregate *aggNode = $1.intermAggregate; + if (aggNode && aggNode->getOp() == EOpNull) + aggNode->setOp(EOpDeclaration); + $$ = aggNode; } | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { if (($2 == EbpHigh) && (context->shaderType == GL_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) { @@ -1102,22 +1072,8 @@ single_declaration $$.intermAggregate = context->parseSingleInitDeclaration($$.type, @2, *$2.string, @3, $4); } | INVARIANT IDENTIFIER { - VERTEX_ONLY("invariant declaration", @1); - if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying")) - context->recover(); - $$.type.setBasic(EbtInvariant, EvqInvariantVaryingOut, @2); - if (!$2.symbol) - { - context->error(@2, "undeclared identifier declared as invariant", $2.string->c_str()); - context->recover(); - - $$.intermAggregate = 0; - } - else - { - TIntermSymbol *symbol = context->intermediate.addSymbol(0, *$2.string, TType($$.type), @2); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); - } + // $$.type is not used in invariant declarations. + $$.intermAggregate = context->parseInvariantDeclaration(@1, @2, $2.string, $2.symbol); } ; diff --git a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp index a6e7ab41a6..56340c6f9e 100644 --- a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp +++ b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp @@ -4,7 +4,7 @@ // found in the LICENSE file. // -#include "compiler/translator/localintermediate.h" +#include "compiler/translator/Intermediate.h" #include "compiler/translator/SymbolTable.h" namespace @@ -342,6 +342,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) case EOpMul: out << "component-wise multiply"; break; case EOpDeclaration: out << "Declaration: "; break; + case EOpInvariantDeclaration: out << "Invariant Declaration: "; break; default: out.prefix(EPrefixError); diff --git a/src/3rdparty/angle/src/compiler/translator/intermediate.h b/src/3rdparty/angle/src/compiler/translator/intermediate.h index 892f2849e0..3b7e7bd802 100644 --- a/src/3rdparty/angle/src/compiler/translator/intermediate.h +++ b/src/3rdparty/angle/src/compiler/translator/intermediate.h @@ -4,768 +4,64 @@ // found in the LICENSE file. // -// -// Definition of the in-memory high-level intermediate representation -// of shaders. This is a tree that parser creates. -// -// Nodes in the tree are defined as a hierarchy of classes derived from -// TIntermNode. Each is a node in a tree. There is no preset branching factor; -// each node can have it's own type of list of children. -// - -#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_ -#define COMPILER_TRANSLATOR_INTERMEDIATE_H_ - -#include "GLSLANG/ShaderLang.h" - -#include -#include - -#include "compiler/translator/Common.h" -#include "compiler/translator/Types.h" -#include "compiler/translator/ConstantUnion.h" - -// -// Operators used by the high-level (parse tree) representation. -// -enum TOperator -{ - EOpNull, // if in a node, should only mean a node is still being built - EOpSequence, // denotes a list of statements, or parameters, etc. - EOpFunctionCall, - EOpFunction, // For function definition - EOpParameters, // an aggregate listing the parameters to a function - - EOpDeclaration, - EOpPrototype, - - // - // Unary operators - // - - EOpNegative, - EOpLogicalNot, - EOpVectorLogicalNot, - - EOpPostIncrement, - EOpPostDecrement, - EOpPreIncrement, - EOpPreDecrement, - - // - // 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 -}; - -class TIntermTraverser; -class TIntermAggregate; -class TIntermBinary; -class TIntermUnary; -class TIntermConstantUnion; -class TIntermSelection; -class TIntermTyped; -class TIntermSymbol; -class TIntermLoop; -class TInfoSink; -class TIntermRaw; - -// -// Base class for the tree nodes -// -class TIntermNode -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - TIntermNode() - { - // TODO: Move this to TSourceLoc constructor - // after getting rid of TPublicType. - mLine.first_file = mLine.last_file = 0; - mLine.first_line = mLine.last_line = 0; - } - virtual ~TIntermNode() { } - - const TSourceLoc &getLine() const { return mLine; } - void setLine(const TSourceLoc &l) { mLine = l; } - - virtual void traverse(TIntermTraverser *) = 0; - virtual TIntermTyped *getAsTyped() { return 0; } - virtual TIntermConstantUnion *getAsConstantUnion() { return 0; } - virtual TIntermAggregate *getAsAggregate() { return 0; } - virtual TIntermBinary *getAsBinaryNode() { return 0; } - virtual TIntermUnary *getAsUnaryNode() { return 0; } - virtual TIntermSelection *getAsSelectionNode() { return 0; } - virtual TIntermSymbol *getAsSymbolNode() { return 0; } - virtual TIntermLoop *getAsLoopNode() { return 0; } - virtual TIntermRaw *getAsRawNode() { return 0; } - - // Replace a child node. Return true if |original| is a child - // node and it is replaced; otherwise, return false. - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement) = 0; - - // For traversing a tree in no particular order, but using - // heap memory. - virtual void enqueueChildren(std::queue *nodeQueue) const = 0; - - protected: - TSourceLoc mLine; -}; - -// -// This is just to help yacc. -// -struct TIntermNodePair -{ - TIntermNode *node1; - TIntermNode *node2; -}; - -// -// Intermediate class for nodes that have a type. -// -class TIntermTyped : public TIntermNode -{ - public: - TIntermTyped(const TType &t) : mType(t) { } - virtual TIntermTyped *getAsTyped() { return this; } +#ifndef COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ +#define COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ - virtual bool hasSideEffects() const = 0; +#include "compiler/translator/IntermNode.h" - void setType(const TType &t) { mType = t; } - const TType &getType() const { return mType; } - TType *getTypePointer() { return &mType; } - - TBasicType getBasicType() const { return mType.getBasicType(); } - TQualifier getQualifier() const { return mType.getQualifier(); } - TPrecision getPrecision() const { return mType.getPrecision(); } - int getCols() const { return mType.getCols(); } - int getRows() const { return mType.getRows(); } - int getNominalSize() const { return mType.getNominalSize(); } - int getSecondarySize() const { return mType.getSecondarySize(); } - - bool isInterfaceBlock() const { return mType.isInterfaceBlock(); } - bool isMatrix() const { return mType.isMatrix(); } - bool isArray() const { return mType.isArray(); } - bool isVector() const { return mType.isVector(); } - bool isScalar() const { return mType.isScalar(); } - bool isScalarInt() const { return mType.isScalarInt(); } - const char *getBasicString() const { return mType.getBasicString(); } - const char *getQualifierString() const { return mType.getQualifierString(); } - TString getCompleteString() const { return mType.getCompleteString(); } - - int getArraySize() const { return mType.getArraySize(); } - - protected: - TType mType; -}; - -// -// Handle for, do-while, and while loops. -// -enum TLoopType +struct TVectorFields { - ELoopFor, - ELoopWhile, - ELoopDoWhile -}; - -class TIntermLoop : public TIntermNode -{ - public: - TIntermLoop(TLoopType type, - TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr, - TIntermNode *body) - : mType(type), - mInit(init), - mCond(cond), - mExpr(expr), - mBody(body), - mUnrollFlag(false) { } - - virtual TIntermLoop *getAsLoopNode() { return this; } - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - TLoopType getType() const { return mType; } - TIntermNode *getInit() { return mInit; } - TIntermTyped *getCondition() { return mCond; } - TIntermTyped *getExpression() { return mExpr; } - TIntermNode *getBody() { return mBody; } - - 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 - TIntermTyped *mCond; // loop exit condition - TIntermTyped *mExpr; // for-loop expression - TIntermNode *mBody; // loop body - - bool mUnrollFlag; // Whether the loop should be unrolled or not. + int offsets[4]; + int num; }; // -// Handle break, continue, return, and kill. +// Set of helper functions to help parse and build the tree. // -class TIntermBranch : public TIntermNode -{ - public: - TIntermBranch(TOperator op, TIntermTyped *e) - : mFlowOp(op), - mExpression(e) { } - - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - 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 -}; - -// -// Nodes that correspond to symbols or constants in the source code. -// -class TIntermSymbol : public TIntermTyped -{ - public: - // if symbol is initialized as symbol(sym), the memory comes from the poolallocator of sym. - // If sym comes from per process globalpoolallocator, then it causes increased memory usage - // per compile it is essential to use "symbol = sym" to assign to symbol - TIntermSymbol(int id, const TString &symbol, const TType &type) - : TIntermTyped(type), - mId(id) - { - mSymbol = symbol; - } - - virtual bool hasSideEffects() const { return false; } - - int getId() const { return mId; } - const TString &getSymbol() const { return mSymbol; } - - void setId(int newId) { mId = newId; } - - virtual void traverse(TIntermTraverser *); - virtual TIntermSymbol *getAsSymbolNode() { return this; } - virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } - - virtual void enqueueChildren(std::queue *nodeQueue) const {} - - protected: - int mId; - TString mSymbol; -}; - -// A Raw node stores raw code, that the translator will insert verbatim -// into the output stream. Useful for transformation operations that make -// complex code that might not fit naturally into the GLSL model. -class TIntermRaw : public TIntermTyped -{ - public: - TIntermRaw(const TType &type, const TString &rawText) - : TIntermTyped(type), - mRawText(rawText) { } - - virtual bool hasSideEffects() const { return false; } - - TString getRawText() const { return mRawText; } - - virtual void traverse(TIntermTraverser *); - - virtual TIntermRaw *getAsRawNode() { return this; } - virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } - virtual void enqueueChildren(std::queue *nodeQueue) const {} - - protected: - TString mRawText; -}; - -class TIntermConstantUnion : public TIntermTyped -{ - public: - TIntermConstantUnion(ConstantUnion *unionPointer, const TType &type) - : TIntermTyped(type), - mUnionArrayPointer(unionPointer) { } - - virtual bool hasSideEffects() const { return false; } - - ConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; } - - int getIConst(size_t index) const - { - return mUnionArrayPointer ? mUnionArrayPointer[index].getIConst() : 0; - } - unsigned int getUConst(size_t index) const - { - return mUnionArrayPointer ? mUnionArrayPointer[index].getUConst() : 0; - } - float getFConst(size_t index) const - { - return mUnionArrayPointer ? mUnionArrayPointer[index].getFConst() : 0.0f; - } - bool getBConst(size_t index) const - { - return mUnionArrayPointer ? mUnionArrayPointer[index].getBConst() : false; - } - - virtual TIntermConstantUnion *getAsConstantUnion() { return this; } - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; } - - TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &); - - virtual void enqueueChildren(std::queue *nodeQueue) const {} - - protected: - ConstantUnion *mUnionArrayPointer; -}; - -// -// Intermediate class for node types that hold operators. -// -class TIntermOperator : public TIntermTyped -{ - public: - TOperator getOp() const { return mOp; } - void setOp(TOperator op) { mOp = op; } - - bool isAssignment() const; - bool isConstructor() const; - - virtual bool hasSideEffects() const { return isAssignment(); } - - protected: - TIntermOperator(TOperator op) - : TIntermTyped(TType(EbtFloat, EbpUndefined)), - mOp(op) {} - TIntermOperator(TOperator op, const TType &type) - : TIntermTyped(type), - mOp(op) {} - - TOperator mOp; -}; - -// -// Nodes for all the basic binary math operators. -// -class TIntermBinary : public TIntermOperator -{ - public: - TIntermBinary(TOperator op) - : TIntermOperator(op), - mAddIndexClamp(false) {} - - virtual TIntermBinary *getAsBinaryNode() { return this; } - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - virtual bool hasSideEffects() const - { - return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects(); - } - - void setLeft(TIntermTyped *node) { mLeft = node; } - void setRight(TIntermTyped *node) { mRight = node; } - TIntermTyped *getLeft() const { return mLeft; } - TIntermTyped *getRight() const { return mRight; } - bool promote(TInfoSink &); - - void setAddIndexClamp() { mAddIndexClamp = true; } - bool getAddIndexClamp() { return mAddIndexClamp; } - - virtual void enqueueChildren(std::queue *nodeQueue) const; - - protected: - TIntermTyped* mLeft; - TIntermTyped* mRight; - - // If set to true, wrap any EOpIndexIndirect with a clamp to bounds. - bool mAddIndexClamp; -}; - -// -// Nodes for unary math operators. -// -class TIntermUnary : public TIntermOperator -{ - public: - TIntermUnary(TOperator op, const TType &type) - : TIntermOperator(op, type), - mOperand(NULL), - mUseEmulatedFunction(false) {} - TIntermUnary(TOperator op) - : TIntermOperator(op), - mOperand(NULL), - mUseEmulatedFunction(false) {} - - virtual void traverse(TIntermTraverser *); - virtual TIntermUnary *getAsUnaryNode() { return this; } - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - virtual bool hasSideEffects() const - { - return isAssignment() || mOperand->hasSideEffects(); - } - - void setOperand(TIntermTyped *operand) { mOperand = operand; } - TIntermTyped *getOperand() { return mOperand; } - bool promote(TInfoSink &); - - void setUseEmulatedFunction() { mUseEmulatedFunction = true; } - bool getUseEmulatedFunction() { return mUseEmulatedFunction; } - - virtual void enqueueChildren(std::queue *nodeQueue) const; - - protected: - TIntermTyped *mOperand; - - // If set to true, replace the built-in function call with an emulated one - // to work around driver bugs. - bool mUseEmulatedFunction; -}; - -typedef TVector TIntermSequence; -typedef TVector TQualifierList; - -// -// Nodes that operate on an arbitrary sized set of children. -// -class TIntermAggregate : public TIntermOperator -{ - public: - TIntermAggregate() - : TIntermOperator(EOpNull), - mUserDefined(false), - mUseEmulatedFunction(false) { } - TIntermAggregate(TOperator op) - : TIntermOperator(op), - mUseEmulatedFunction(false) { } - ~TIntermAggregate() { } - - virtual TIntermAggregate *getAsAggregate() { return this; } - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - // Conservatively assume function calls and other aggregate operators have side-effects - virtual bool hasSideEffects() const { return true; } - - TIntermSequence *getSequence() { return &mSequence; } - - void setName(const TString &name) { mName = name; } - const TString &getName() const { return mName; } - - void setUserDefined() { mUserDefined = true; } - bool isUserDefined() const { return mUserDefined; } - - void setOptimize(bool optimize) { mOptimize = optimize; } - bool getOptimize() const { return mOptimize; } - void setDebug(bool debug) { mDebug = debug; } - bool getDebug() const { return mDebug; } - - void setUseEmulatedFunction() { mUseEmulatedFunction = true; } - bool getUseEmulatedFunction() { return mUseEmulatedFunction; } - - virtual void enqueueChildren(std::queue *nodeQueue) const; - - protected: - TIntermAggregate(const TIntermAggregate &); // disallow copy constructor - TIntermAggregate &operator=(const TIntermAggregate &); // disallow assignment operator - TIntermSequence mSequence; - TString mName; - bool mUserDefined; // used for user defined function names - - bool mOptimize; - bool mDebug; - - // If set to true, replace the built-in function call with an emulated one - // to work around driver bugs. - bool mUseEmulatedFunction; -}; - -// -// For if tests. Simplified since there is no switch statement. -// -class TIntermSelection : public TIntermTyped -{ - public: - TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB) - : TIntermTyped(TType(EbtVoid, EbpUndefined)), - mCondition(cond), - mTrueBlock(trueB), - mFalseBlock(falseB) {} - TIntermSelection(TIntermTyped *cond, TIntermNode *trueB, TIntermNode *falseB, - const TType &type) - : TIntermTyped(type), - mCondition(cond), - mTrueBlock(trueB), - mFalseBlock(falseB) {} - - virtual void traverse(TIntermTraverser *); - virtual bool replaceChildNode( - TIntermNode *original, TIntermNode *replacement); - - // Conservatively assume selections have side-effects - virtual bool hasSideEffects() const { return true; } - - bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } - TIntermNode *getCondition() const { return mCondition; } - TIntermNode *getTrueBlock() const { return mTrueBlock; } - TIntermNode *getFalseBlock() const { return mFalseBlock; } - TIntermSelection *getAsSelectionNode() { return this; } - - virtual void enqueueChildren(std::queue *nodeQueue) const; - -protected: - TIntermTyped *mCondition; - TIntermNode *mTrueBlock; - TIntermNode *mFalseBlock; -}; - -enum Visit -{ - PreVisit, - InVisit, - PostVisit -}; - -// -// For traversing the tree. User should derive from this, -// put their traversal specific data in it, and then pass -// it to a Traverse method. -// -// When using this, just fill in the methods for nodes you want visited. -// Return false from a pre-visit to skip visiting that node's subtree. -// -class TIntermTraverser -{ - public: - POOL_ALLOCATOR_NEW_DELETE(); - // TODO(zmo): remove default values. - TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, - bool rightToLeft = false) - : preVisit(preVisit), - inVisit(inVisit), - postVisit(postVisit), - rightToLeft(rightToLeft), - mDepth(0), - mMaxDepth(0) {} - virtual ~TIntermTraverser() {} - - virtual void visitSymbol(TIntermSymbol *) {} - virtual void visitRaw(TIntermRaw *) {} - virtual void visitConstantUnion(TIntermConstantUnion *) {} - virtual bool visitBinary(Visit, TIntermBinary *) { return true; } - virtual bool visitUnary(Visit, TIntermUnary *) { return true; } - virtual bool visitSelection(Visit, TIntermSelection *) { return true; } - virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; } - virtual bool visitLoop(Visit, TIntermLoop *) { return true; } - virtual bool visitBranch(Visit, TIntermBranch *) { return true; } - - int getMaxDepth() const { return mMaxDepth; } - - void incrementDepth(TIntermNode *current) - { - mDepth++; - mMaxDepth = std::max(mMaxDepth, mDepth); - mPath.push_back(current); - } - - void decrementDepth() - { - mDepth--; - mPath.pop_back(); - } - - TIntermNode *getParentNode() - { - return mPath.size() == 0 ? NULL : mPath.back(); - } - - // Return the original name if hash function pointer is NULL; - // otherwise return the hashed name. - static TString hash(const TString& name, ShHashFunction64 hashFunction); - - const bool preVisit; - const bool inVisit; - const bool postVisit; - const bool rightToLeft; - - protected: - int mDepth; - int mMaxDepth; - - // All the nodes from root to the current node's parent during traversing. - TVector mPath; -}; - -// -// For traversing the tree, and computing max depth. -// Takes a maximum depth limit to prevent stack overflow. -// -class TMaxDepthTraverser : public TIntermTraverser +class TInfoSink; +class TIntermediate { public: POOL_ALLOCATOR_NEW_DELETE(); - TMaxDepthTraverser(int depthLimit) - : TIntermTraverser(true, true, false, false), - mDepthLimit(depthLimit) { } - - virtual bool visitBinary(Visit, TIntermBinary *) { return depthCheck(); } - virtual bool visitUnary(Visit, TIntermUnary *) { return depthCheck(); } - virtual bool visitSelection(Visit, TIntermSelection *) { return depthCheck(); } - virtual bool visitAggregate(Visit, TIntermAggregate *) { return depthCheck(); } - virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); } - virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); } - -protected: - bool depthCheck() const { return mMaxDepth < mDepthLimit; } - - int mDepthLimit; -}; - -#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_ + 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/localintermediate.h b/src/3rdparty/angle/src/compiler/translator/localintermediate.h deleted file mode 100644 index 0809bbd362..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/localintermediate.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/intermediate.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/timing/RestrictFragmentShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h index e77d8c21cb..80d5f7fa7f 100644 --- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ #define COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/depgraph/DependencyGraph.h" class TInfoSinkBase; diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h index d461fbdbfe..a6263567b4 100644 --- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h @@ -7,7 +7,7 @@ #ifndef COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ #define COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" #include "compiler/translator/InfoSink.h" class TInfoSinkBase; diff --git a/src/3rdparty/angle/src/compiler/translator/util.cpp b/src/3rdparty/angle/src/compiler/translator/util.cpp index 561d4e007c..f74c7d1173 100644 --- a/src/3rdparty/angle/src/compiler/translator/util.cpp +++ b/src/3rdparty/angle/src/compiler/translator/util.cpp @@ -9,7 +9,6 @@ #include #include "compiler/preprocessor/numeric_lex.h" -#include "common/shadervars.h" #include "common/utilities.h" bool atof_clamp(const char *str, float *value) @@ -269,6 +268,8 @@ InterpolationType GetInterpolationType(TQualifier qualifier) case EvqFragmentIn: case EvqVaryingIn: case EvqVaryingOut: + case EvqInvariantVaryingIn: + case EvqInvariantVaryingOut: return INTERPOLATION_SMOOTH; case EvqCentroidIn: @@ -281,7 +282,7 @@ InterpolationType GetInterpolationType(TQualifier qualifier) } template -void GetVariableTraverser::traverse(const TType &type, const TString &name) +void GetVariableTraverser::traverse(const TType &type, const TString &name, std::vector *output) { const TStructure *structure = type.getStruct(); @@ -296,61 +297,27 @@ void GetVariableTraverser::traverse(const TType &type, const TString &name } else { + // Note: this enum value is not exposed outside ANGLE variable.type = GL_STRUCT_ANGLEX; - - mOutputStack.push(&variable.fields); + variable.structName = structure->name().c_str(); const TFieldList &fields = structure->fields(); for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) { TField *field = fields[fieldIndex]; - traverse(*field->type(), field->name()); + traverse(*field->type(), field->name(), &variable.fields); } - - mOutputStack.pop(); } visitVariable(&variable); - ASSERT(!mOutputStack.empty()); - mOutputStack.top()->push_back(variable); -} - -template -GetVariableTraverser::GetVariableTraverser(std::vector *output) -{ ASSERT(output); - mOutputStack.push(output); + output->push_back(variable); } -template class GetVariableTraverser; -template class GetVariableTraverser; -template class GetVariableTraverser; - -GetInterfaceBlockFieldTraverser::GetInterfaceBlockFieldTraverser(std::vector *output, bool isRowMajorMatrix) - : GetVariableTraverser(output), - mIsRowMajorMatrix(isRowMajorMatrix) -{ -} - -void GetInterfaceBlockFieldTraverser::visitVariable(InterfaceBlockField *newField) -{ - if (gl::IsMatrixType(newField->type)) - { - newField->isRowMajorMatrix = mIsRowMajorMatrix; - } -} - -BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage) -{ - switch (blockStorage) - { - case EbsPacked: return BLOCKLAYOUT_PACKED; - case EbsShared: return BLOCKLAYOUT_SHARED; - case EbsStd140: return BLOCKLAYOUT_STANDARD; - default: UNREACHABLE(); return BLOCKLAYOUT_SHARED; - } -} +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector *); +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector *); +template void GetVariableTraverser::traverse(const TType &, const TString &, std::vector *); } diff --git a/src/3rdparty/angle/src/compiler/translator/util.h b/src/3rdparty/angle/src/compiler/translator/util.h index 5c214dd4fb..241e2cc1c2 100644 --- a/src/3rdparty/angle/src/compiler/translator/util.h +++ b/src/3rdparty/angle/src/compiler/translator/util.h @@ -9,9 +9,10 @@ #include -#include "compiler/translator/Types.h" #include "angle_gl.h" -#include "common/shadervars.h" +#include + +#include "compiler/translator/Types.h" // atof_clamp is like atof but // 1. it forces C locale, i.e. forcing '.' as decimal point. @@ -32,33 +33,22 @@ bool IsVaryingIn(TQualifier qualifier); bool IsVaryingOut(TQualifier qualifier); bool IsVarying(TQualifier qualifier); InterpolationType GetInterpolationType(TQualifier qualifier); -BlockLayoutType GetBlockLayoutType(TLayoutBlockStorage blockStorage); TString ArrayString(const TType &type); -template class GetVariableTraverser { public: - GetVariableTraverser(std::vector *output); - void traverse(const TType &type, const TString &name); + GetVariableTraverser() {} + + template + void traverse(const TType &type, const TString &name, std::vector *output); protected: // May be overloaded - virtual void visitVariable(VarT *newVar) {} + virtual void visitVariable(ShaderVariable *newVar) {} private: - std::stack *> mOutputStack; -}; - -struct GetInterfaceBlockFieldTraverser : public GetVariableTraverser -{ - public: - GetInterfaceBlockFieldTraverser(std::vector *output, bool isRowMajorMatrix); - - private: - virtual void visitVariable(InterfaceBlockField *newField); - - bool mIsRowMajorMatrix; + DISALLOW_COPY_AND_ASSIGN(GetVariableTraverser); }; } diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp index 7cd83c3db4..5a50e4baf5 100644 --- a/src/3rdparty/angle/src/libEGL/Display.cpp +++ b/src/3rdparty/angle/src/libEGL/Display.cpp @@ -561,8 +561,10 @@ void Display::initDisplayExtensionString() 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"); + extensions.push_back("EGL_KHR_create_context"); +#endif std::ostringstream stream; std::copy(extensions.begin(), extensions.end(), std::ostream_iterator(stream, " ")); @@ -606,6 +608,7 @@ void Display::initVendorString() { char adapterLuidString[64]; snprintf(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart); + mVendorString += adapterLuidString; } } diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp index c236d52a4f..c2e0fd6d3d 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" @@ -825,12 +828,19 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface 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) + { + return egl::error(EGL_BAD_MATCH, EGL_FALSE); + } + if (ctx != EGL_NO_CONTEXT && !validateContext(display, context)) { return EGL_FALSE; } - if (dpy != EGL_NO_DISPLAY) + if (dpy != EGL_NO_DISPLAY && display->isInitialized()) { rx::Renderer *renderer = display->getRenderer(); if (renderer->testDeviceLost(true)) diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp index 5788af7827..e74737eaba 100644 --- a/src/3rdparty/angle/src/libEGL/main.cpp +++ b/src/3rdparty/angle/src/libEGL/main.cpp @@ -105,15 +105,15 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved break; case DLL_THREAD_DETACH: { +#if !defined(ANGLE_PLATFORM_WINRT) egl::DeallocateCurrent(); +#endif } break; case DLL_PROCESS_DETACH: { -#if !defined(ANGLE_PLATFORM_WINRT) egl::DeallocateCurrent(); DestroyTLSIndex(currentTLS); -#endif } break; default: diff --git a/src/3rdparty/angle/src/libEGL/main.h b/src/3rdparty/angle/src/libEGL/main.h index 6030fb6ad9..07f5b9e675 100644 --- a/src/3rdparty/angle/src/libEGL/main.h +++ b/src/3rdparty/angle/src/libEGL/main.h @@ -9,8 +9,6 @@ #ifndef LIBEGL_MAIN_H_ #define LIBEGL_MAIN_H_ -#undef EGLAPI -#define EGLAPI #include #include diff --git a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h index 1cbfc6751d..4d7dde04e1 100644 --- a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h +++ b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h @@ -12,6 +12,10 @@ #include "common/angleutils.h" #include "common/mathutil.h" +#include +#include +#include + namespace gl { diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp index a47b8f402f..3b2a1a912a 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -31,59 +30,99 @@ Buffer::Buffer(rx::BufferImpl *impl, GLuint id) Buffer::~Buffer() { - delete mBuffer; + SafeDelete(mBuffer); } -void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) +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; - mBuffer->setData(data, size, usage); + + return error; } -void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) +Error Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) { - mBuffer->setSubData(data, size, offset); + gl::Error error = mBuffer->setSubData(data, size, offset); + if (error.isError()) + { + return error; + } + + mIndexRangeCache.invalidateRange(offset, size); + + return error; } -void Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +Error Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) { - mBuffer->copySubData(source->getImplementation(), size, sourceOffset, destOffset); + gl::Error error = mBuffer->copySubData(source->getImplementation(), sourceOffset, destOffset, size); + if (error.isError()) + { + return error; + } + + mIndexRangeCache.invalidateRange(destOffset, size); + + return error; } -GLvoid *Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access) +Error Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access) { ASSERT(!mMapped); ASSERT(offset + length <= mSize); - void *dataPointer = mBuffer->map(offset, length, access); + Error error = mBuffer->map(offset, length, access, &mMapPointer); + if (error.isError()) + { + mMapPointer = NULL; + return error; + } mMapped = GL_TRUE; - mMapPointer = static_cast(static_cast(dataPointer)); mMapOffset = static_cast(offset); mMapLength = static_cast(length); mAccessFlags = static_cast(access); - return mMapPointer; + if ((access & GL_MAP_WRITE_BIT) > 0) + { + mIndexRangeCache.invalidateRange(offset, length); + } + + return error; } -void Buffer::unmap() +Error Buffer::unmap() { ASSERT(mMapped); - mBuffer->unmap(); + 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 index 389c3d4b00..35a6767502 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Buffer.h @@ -11,8 +11,11 @@ #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 { @@ -30,13 +33,13 @@ class Buffer : public RefCountObject virtual ~Buffer(); - void bufferData(const void *data, GLsizeiptr size, GLenum usage); - void bufferSubData(const void *data, GLsizeiptr size, GLintptr offset); - void copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); - GLvoid *mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access); - void unmap(); + 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; } + GLenum getUsage() const { return mUsage; } GLint getAccessFlags() const { return mAccessFlags; } GLboolean isMapped() const { return mMapped; } GLvoid *getMapPointer() const { return mMapPointer; } @@ -48,18 +51,23 @@ class Buffer : public RefCountObject 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; - GLsizeiptr mSize; + GLint64 mSize; GLint mAccessFlags; GLboolean mMapped; GLvoid *mMapPointer; GLint64 mMapOffset; GLint64 mMapLength; + + rx::IndexRangeCache mIndexRangeCache; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/Caps.cpp b/src/3rdparty/angle/src/libGLESv2/Caps.cpp index c1c4dc9ee7..983800c0e6 100644 --- a/src/3rdparty/angle/src/libGLESv2/Caps.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Caps.cpp @@ -24,6 +24,30 @@ TextureCaps::TextureCaps() { } +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)); @@ -158,12 +182,17 @@ std::vector Extensions::getStrings() const } static bool GetFormatSupport(const TextureCapsMap &textureCaps, const std::vector &requiredFormats, - bool requiresFiltering, bool requiresRendering) + 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; @@ -185,7 +214,7 @@ static bool DetermineRGB8AndRGBA8TextureSupport(const TextureCapsMap &textureCap requiredFormats.push_back(GL_RGB8); requiredFormats.push_back(GL_RGBA8); - return GetFormatSupport(textureCaps, requiredFormats, true, true); + return GetFormatSupport(textureCaps, requiredFormats, true, true, true); } // Checks for GL_EXT_texture_format_BGRA8888 support @@ -194,7 +223,7 @@ static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps) std::vector requiredFormats; requiredFormats.push_back(GL_BGRA8_EXT); - return GetFormatSupport(textureCaps, requiredFormats, true, true); + return GetFormatSupport(textureCaps, requiredFormats, true, true, true); } // Checks for GL_OES_texture_half_float support @@ -204,7 +233,7 @@ static bool DetermineHalfFloatTextureSupport(const TextureCapsMap &textureCaps) requiredFormats.push_back(GL_RGB16F); requiredFormats.push_back(GL_RGBA16F); - return GetFormatSupport(textureCaps, requiredFormats, false, true); + return GetFormatSupport(textureCaps, requiredFormats, true, false, true); } // Checks for GL_OES_texture_half_float_linear support @@ -214,7 +243,7 @@ static bool DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap &text requiredFormats.push_back(GL_RGB16F); requiredFormats.push_back(GL_RGBA16F); - return GetFormatSupport(textureCaps, requiredFormats, true, false); + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); } // Checks for GL_OES_texture_float support @@ -224,7 +253,7 @@ static bool DetermineFloatTextureSupport(const TextureCapsMap &textureCaps) requiredFormats.push_back(GL_RGB32F); requiredFormats.push_back(GL_RGBA32F); - return GetFormatSupport(textureCaps, requiredFormats, false, true); + return GetFormatSupport(textureCaps, requiredFormats, true, false, true); } // Checks for GL_OES_texture_float_linear support @@ -234,7 +263,7 @@ static bool DetermineFloatTextureFilteringSupport(const TextureCapsMap &textureC requiredFormats.push_back(GL_RGB32F); requiredFormats.push_back(GL_RGBA32F); - return GetFormatSupport(textureCaps, requiredFormats, true, false); + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); } // Checks for GL_EXT_texture_rg support @@ -254,7 +283,7 @@ static bool DetermineRGTextureSupport(const TextureCapsMap &textureCaps, bool ch requiredFormats.push_back(GL_RG32F); } - return GetFormatSupport(textureCaps, requiredFormats, true, false); + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); } // Check for GL_EXT_texture_compression_dxt1 @@ -264,7 +293,7 @@ static bool DetermineDXT1TextureSupport(const TextureCapsMap &textureCaps) requiredFormats.push_back(GL_COMPRESSED_RGB_S3TC_DXT1_EXT); requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); - return GetFormatSupport(textureCaps, requiredFormats, true, false); + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); } // Check for GL_ANGLE_texture_compression_dxt3 @@ -273,7 +302,7 @@ static bool DetermineDXT3TextureSupport(const TextureCapsMap &textureCaps) std::vector requiredFormats; requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); - return GetFormatSupport(textureCaps, requiredFormats, true, false); + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); } // Check for GL_ANGLE_texture_compression_dxt5 @@ -282,7 +311,7 @@ static bool DetermineDXT5TextureSupport(const TextureCapsMap &textureCaps) std::vector requiredFormats; requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); - return GetFormatSupport(textureCaps, requiredFormats, true, false); + return GetFormatSupport(textureCaps, requiredFormats, true, true, false); } // Check for GL_ANGLE_texture_compression_dxt5 @@ -295,8 +324,8 @@ static bool DetermineSRGBTextureSupport(const TextureCapsMap &textureCaps) std::vector requiredRenderFormats; requiredRenderFormats.push_back(GL_SRGB8_ALPHA8); - return GetFormatSupport(textureCaps, requiredFilterFormats, true, false) && - GetFormatSupport(textureCaps, requiredRenderFormats, false, true); + return GetFormatSupport(textureCaps, requiredFilterFormats, true, true, false) && + GetFormatSupport(textureCaps, requiredRenderFormats, true, false, true); } // Check for GL_ANGLE_depth_texture @@ -307,7 +336,7 @@ static bool DetermineDepthTextureSupport(const TextureCapsMap &textureCaps) requiredFormats.push_back(GL_DEPTH_COMPONENT32_OES); requiredFormats.push_back(GL_DEPTH24_STENCIL8_OES); - return GetFormatSupport(textureCaps, requiredFormats, true, true); + return GetFormatSupport(textureCaps, requiredFormats, true, true, true); } // Check for GL_EXT_color_buffer_float @@ -322,7 +351,7 @@ static bool DetermineColorBufferFloatSupport(const TextureCapsMap &textureCaps) requiredFormats.push_back(GL_RGBA32F); requiredFormats.push_back(GL_R11F_G11F_B10F); - return GetFormatSupport(textureCaps, requiredFormats, false, true); + return GetFormatSupport(textureCaps, requiredFormats, true, false, true); } void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps) @@ -356,7 +385,40 @@ Caps::Caps() maxViewportHeight(0), minAliasedPointSize(0), maxAliasedPointSize(0), - minAliasedLineWidth(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 index a08618ec9c..a00e554176 100644 --- a/src/3rdparty/angle/src/libGLESv2/Caps.h +++ b/src/3rdparty/angle/src/libGLESv2/Caps.h @@ -17,6 +17,8 @@ namespace gl { +typedef std::set SupportedSampleSet; + struct TextureCaps { TextureCaps(); @@ -30,7 +32,14 @@ struct TextureCaps // Support for being used as a framebuffer attachment or renderbuffer format bool renderable; - std::set sampleCounts; + 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 @@ -68,6 +77,7 @@ struct Extensions // 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); @@ -166,6 +176,7 @@ struct Extensions // GL_ANGLE_framebuffer_multisample bool framebufferMultisample; + GLuint maxSamples; // GL_ANGLE_instanced_arrays bool instancedArrays; @@ -215,6 +226,46 @@ struct Caps 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; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp index 99df85b0d3..5342de1331 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -12,6 +11,7 @@ #include "libGLESv2/main.h" #include "common/utilities.h" +#include "common/platform.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Fence.h" @@ -24,7 +24,6 @@ #include "libGLESv2/Texture.h" #include "libGLESv2/ResourceManager.h" #include "libGLESv2/renderer/d3d/IndexDataManager.h" -#include "libGLESv2/renderer/RenderTarget.h" #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/VertexArray.h" #include "libGLESv2/Sampler.h" @@ -33,8 +32,8 @@ #include "libEGL/Surface.h" -#undef near -#undef far +#include +#include namespace gl { @@ -45,6 +44,7 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere ASSERT(robustAccess == false); // Unimplemented initCaps(clientVersion); + mState.initialize(mCaps, clientVersion); mClientVersion = clientVersion; @@ -66,16 +66,26 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere // In order that access to these initial textures not be lost, they are treated as texture // objects all of whose names are 0. - mTexture2DZero.set(new Texture2D(mRenderer->createTexture2D(), 0)); - mTextureCubeMapZero.set(new TextureCubeMap(mRenderer->createTextureCube(), 0)); - mTexture3DZero.set(new Texture3D(mRenderer->createTexture3D(), 0)); - mTexture2DArrayZero.set(new Texture2DArray(mRenderer->createTexture2DArray(), 0)); + mZeroTextures[GL_TEXTURE_2D].set(new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), 0)); + bindTexture(GL_TEXTURE_2D, 0); + + mZeroTextures[GL_TEXTURE_CUBE_MAP].set(new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0)); + bindTexture(GL_TEXTURE_CUBE_MAP, 0); + + if (mClientVersion >= 3) + { + // TODO: These could also be enabled via extension + mZeroTextures[GL_TEXTURE_3D].set(new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), 0)); + bindTexture(GL_TEXTURE_3D, 0); + + mZeroTextures[GL_TEXTURE_2D_ARRAY].set(new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0)); + bindTexture(GL_TEXTURE_2D_ARRAY, 0); + } bindVertexArray(0); bindArrayBuffer(0); bindElementArrayBuffer(0); - bindTextureCubeMap(0); - bindTexture2D(0); + bindReadFramebuffer(0); bindDrawFramebuffer(0); bindRenderbuffer(0); @@ -101,23 +111,15 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere // 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(0)); + mTransformFeedbackZero.set(new TransformFeedback(mRenderer->createTransformFeedback(), 0)); bindTransformFeedback(0); - mInvalidEnum = false; - mInvalidValue = false; - mInvalidOperation = false; - mOutOfMemory = false; - mInvalidFramebufferOperation = false; - mHasBeenCurrent = false; mContextLost = false; mResetStatus = GL_NO_ERROR; mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT); mRobustAccess = robustAccess; - mNumCompressedTextureFormats = 0; - mState.setContext(this); } @@ -161,15 +163,17 @@ Context::~Context() deleteTransformFeedback(mTransformFeedbackMap.begin()->first); } - for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) + for (TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); i++) { - mIncompleteTextures[type].set(NULL); + i->second.set(NULL); } + mIncompleteTextures.clear(); - mTexture2DZero.set(NULL); - mTextureCubeMapZero.set(NULL); - mTexture3DZero.set(NULL); - mTexture2DArrayZero.set(NULL); + for (TextureMap::iterator i = mZeroTextures.begin(); i != mZeroTextures.end(); i++) + { + i->second.set(NULL); + } + mZeroTextures.clear(); mResourceManager->release(); } @@ -178,23 +182,6 @@ void Context::makeCurrent(egl::Surface *surface) { if (!mHasBeenCurrent) { - mMajorShaderModel = mRenderer->getMajorShaderModel(); - mSupportsVertexTexture = mRenderer->getVertexTextureSupport(); - - mNumCompressedTextureFormats = 0; - if (mExtensions.textureCompressionDXT1) - { - mNumCompressedTextureFormats += 2; - } - if (mExtensions.textureCompressionDXT3) - { - mNumCompressedTextureFormats += 1; - } - if (mExtensions.textureCompressionDXT5) - { - mNumCompressedTextureFormats += 1; - } - initRendererString(); initExtensionStrings(); @@ -287,7 +274,7 @@ GLuint Context::createSampler() GLuint Context::createTransformFeedback() { GLuint handle = mTransformFeedbackAllocator.allocate(); - TransformFeedback *transformFeedback = new TransformFeedback(handle); + TransformFeedback *transformFeedback = new TransformFeedback(mRenderer->createTransformFeedback(), handle); transformFeedback->addRef(); mTransformFeedbackMap[handle] = transformFeedback; return handle; @@ -528,32 +515,11 @@ void Context::bindElementArrayBuffer(unsigned int buffer) mState.getVertexArray()->setElementArrayBuffer(getBuffer(buffer)); } -void Context::bindTexture2D(GLuint texture) +void Context::bindTexture(GLenum target, GLuint texture) { - mResourceManager->checkTextureAllocation(texture, TEXTURE_2D); + mResourceManager->checkTextureAllocation(texture, target); - mState.setSamplerTexture(TEXTURE_2D, getTexture(texture)); -} - -void Context::bindTextureCubeMap(GLuint texture) -{ - mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE); - - mState.setSamplerTexture(TEXTURE_CUBE, getTexture(texture)); -} - -void Context::bindTexture3D(GLuint texture) -{ - mResourceManager->checkTextureAllocation(texture, TEXTURE_3D); - - mState.setSamplerTexture(TEXTURE_3D, getTexture(texture)); -} - -void Context::bindTexture2DArray(GLuint texture) -{ - mResourceManager->checkTextureAllocation(texture, TEXTURE_2D_ARRAY); - - mState.setSamplerTexture(TEXTURE_2D_ARRAY, getTexture(texture)); + mState.setSamplerTexture(target, getTexture(texture)); } void Context::bindReadFramebuffer(GLuint framebuffer) @@ -596,7 +562,7 @@ void Context::bindVertexArray(GLuint vertexArray) void Context::bindSampler(GLuint textureUnit, GLuint sampler) { - ASSERT(textureUnit < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS); // TODO: Update for backend-determined array size + ASSERT(textureUnit < mCaps.maxCombinedTextureImageUnits); mResourceManager->checkSamplerAllocation(sampler); mState.setSamplerBinding(textureUnit, getSampler(sampler)); @@ -678,7 +644,7 @@ void Context::linkProgram(GLuint program) { Program *programObject = mResourceManager->getProgram(program); - bool linked = programObject->link(); + bool linked = programObject->link(getCaps()); // if the current program was relinked successfully we // need to install the new executables @@ -688,11 +654,11 @@ void Context::linkProgram(GLuint program) } } -void Context::setProgramBinary(GLuint program, const void *binary, GLint length) +void Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length) { Program *programObject = mResourceManager->getProgram(program); - bool loaded = programObject->setProgramBinary(binary, length); + bool loaded = programObject->setProgramBinary(binaryFormat, binary, length); // if the current program was reloaded successfully we // need to install the new executables @@ -708,26 +674,35 @@ void Context::bindTransformFeedback(GLuint transformFeedback) mState.setTransformFeedbackBinding(getTransformFeedback(transformFeedback)); } -void Context::beginQuery(GLenum target, GLuint query) +Error Context::beginQuery(GLenum target, GLuint query) { Query *queryObject = getQuery(query, true, target); ASSERT(queryObject); - // set query as active for specified target + // 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); - // begin query - queryObject->begin(); + return Error(GL_NO_ERROR); } -void Context::endQuery(GLenum target) +Error Context::endQuery(GLenum target) { Query *queryObject = mState.getActiveQuery(target); ASSERT(queryObject); - queryObject->end(); + 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) @@ -755,15 +730,16 @@ void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum inter RenderbufferStorage *renderbuffer = NULL; - if (GetDepthBits(internalformat) > 0 && GetStencilBits(internalformat) > 0) + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (formatInfo.depthBits > 0 && formatInfo.stencilBits > 0) { renderbuffer = new gl::DepthStencilbuffer(mRenderer, width, height, samples); } - else if (GetDepthBits(internalformat) > 0) + else if (formatInfo.depthBits > 0) { renderbuffer = new gl::Depthbuffer(mRenderer, width, height, samples); } - else if (GetStencilBits(internalformat) > 0) + else if (formatInfo.stencilBits > 0) { renderbuffer = new gl::Stencilbuffer(mRenderer, width, height, samples); } @@ -815,7 +791,7 @@ Query *Context::getQuery(unsigned int handle, bool create, GLenum type) { if (!query->second && create) { - query->second = new Query(mRenderer, type, handle); + query->second = new Query(mRenderer->createQuery(type), handle); query->second->addRef(); } return query->second; @@ -841,36 +817,29 @@ Texture *Context::getTargetTexture(GLenum target) const Texture2D *Context::getTexture2D() const { - return static_cast(getSamplerTexture(mState.getActiveSampler(), TEXTURE_2D)); + return static_cast(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_2D)); } TextureCubeMap *Context::getTextureCubeMap() const { - return static_cast(getSamplerTexture(mState.getActiveSampler(), TEXTURE_CUBE)); + return static_cast(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_CUBE_MAP)); } Texture3D *Context::getTexture3D() const { - return static_cast(getSamplerTexture(mState.getActiveSampler(), TEXTURE_3D)); + return static_cast(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_3D)); } Texture2DArray *Context::getTexture2DArray() const { - return static_cast(getSamplerTexture(mState.getActiveSampler(), TEXTURE_2D_ARRAY)); + return static_cast(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_2D_ARRAY)); } -Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type) const +Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const { if (mState.getSamplerTextureId(sampler, type) == 0) { - switch (type) - { - default: UNREACHABLE(); - case TEXTURE_2D: return mTexture2DZero.get(); - case TEXTURE_CUBE: return mTextureCubeMapZero.get(); - case TEXTURE_3D: return mTexture3DZero.get(); - case TEXTURE_2D_ARRAY: return mTexture2DArrayZero.get(); - } + return mZeroTextures.at(type).get(); } else { @@ -921,45 +890,39 @@ void Context::getIntegerv(GLenum pname, GLint *params) switch (pname) { - case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break; - case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = mRenderer->getMaxVertexUniformVectors(); break; - case GL_MAX_VERTEX_UNIFORM_COMPONENTS: *params = mRenderer->getMaxVertexUniformVectors() * 4; break; - case GL_MAX_VARYING_VECTORS: *params = mRenderer->getMaxVaryingVectors(); break; - case GL_MAX_VARYING_COMPONENTS: *params = mRenderer->getMaxVaryingVectors() * 4; break; - case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = mRenderer->getMaxCombinedTextureImageUnits(); break; - case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = mRenderer->getMaxVertexTextureImageUnits(); break; - case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break; - case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = mRenderer->getMaxFragmentUniformVectors(); break; - case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: *params = mRenderer->getMaxFragmentUniformVectors() * 4; break; + 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_NUM_SHADER_BINARY_FORMATS: *params = 0; break; - case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ 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 = getUniformBufferOffsetAlignment(); break; - case GL_MAX_UNIFORM_BUFFER_BINDINGS: *params = getMaximumCombinedUniformBufferBindings(); break; - case GL_MAX_VERTEX_UNIFORM_BLOCKS: *params = mRenderer->getMaxVertexShaderUniformBuffers(); break; - case GL_MAX_FRAGMENT_UNIFORM_BLOCKS: *params = mRenderer->getMaxFragmentShaderUniformBuffers(); break; - case GL_MAX_COMBINED_UNIFORM_BLOCKS: *params = getMaximumCombinedUniformBufferBindings(); 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 = mRenderer->getMaxRecommendedElementsIndices(); break; - case GL_MAX_ELEMENTS_VERTICES: *params = mRenderer->getMaxRecommendedElementsVertices(); break; - case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: *params = mRenderer->getMaxTransformFeedbackInterleavedComponents(); break; - case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: *params = mRenderer->getMaxTransformFeedbackBuffers(); break; - case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: *params = mRenderer->getMaxTransformFeedbackSeparateComponents(); break; - case GL_NUM_COMPRESSED_TEXTURE_FORMATS: - params[0] = mNumCompressedTextureFormats; - break; - case GL_MAX_SAMPLES_ANGLE: - *params = static_cast(getMaxSupportedSamples()); - 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: { @@ -978,30 +941,22 @@ void Context::getIntegerv(GLenum pname, GLint *params) } break; case GL_COMPRESSED_TEXTURE_FORMATS: - { - if (mExtensions.textureCompressionDXT1) - { - *params++ = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; - *params++ = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - } - if (mExtensions.textureCompressionDXT3) - { - *params++ = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE; - } - if (mExtensions.textureCompressionDXT5) - { - *params++ = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE; - } - } + std::copy(mCaps.compressedTextureFormats.begin(), mCaps.compressedTextureFormats.end(), params); break; case GL_RESET_NOTIFICATION_STRATEGY_EXT: *params = mResetStrategy; break; - case GL_NUM_PROGRAM_BINARY_FORMATS_OES: - *params = 1; + case GL_NUM_SHADER_BINARY_FORMATS: + *params = mCaps.shaderBinaryFormats.size(); break; - case GL_PROGRAM_BINARY_FORMATS_OES: - *params = GL_PROGRAM_BINARY_ANGLE; + 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()); @@ -1022,25 +977,16 @@ void Context::getInteger64v(GLenum pname, GLint64 *params) *params = mCaps.maxElementIndex; break; case GL_MAX_UNIFORM_BLOCK_SIZE: - *params = static_cast(mRenderer->getMaxUniformBufferSize()); + *params = mCaps.maxUniformBlockSize; break; case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: - { - GLint64 uniformBufferComponents = static_cast(mRenderer->getMaxVertexShaderUniformBuffers()) * static_cast(mRenderer->getMaxUniformBufferSize() / 4); - GLint64 defaultBufferComponents = static_cast(mRenderer->getMaxVertexUniformVectors() * 4); - *params = uniformBufferComponents + defaultBufferComponents; - } + *params = mCaps.maxCombinedVertexUniformComponents; break; case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: - { - GLint64 uniformBufferComponents = static_cast(mRenderer->getMaxFragmentShaderUniformBuffers()) * static_cast(mRenderer->getMaxUniformBufferSize() / 4); - GLint64 defaultBufferComponents = static_cast(mRenderer->getMaxVertexUniformVectors() * 4); - *params = uniformBufferComponents + defaultBufferComponents; - } + *params = mCaps.maxCombinedFragmentUniformComponents; break; case GL_MAX_SERVER_WAIT_TIMEOUT: - // We do not wait for server fence objects internally, so report a max timeout of zero. - *params = 0; + *params = mCaps.maxServerWaitTimeout; break; default: UNREACHABLE(); @@ -1087,13 +1033,19 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_COMPRESSED_TEXTURE_FORMATS: { *type = GL_INT; - *numParams = mNumCompressedTextureFormats; + *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 = 0; + *numParams = mCaps.shaderBinaryFormats.size(); } return true; case GL_MAX_VERTEX_ATTRIBS: @@ -1162,7 +1114,6 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_TEXTURE_BINDING_CUBE_MAP: case GL_RESET_NOTIFICATION_STRATEGY_EXT: case GL_NUM_PROGRAM_BINARY_FORMATS_OES: - case GL_PROGRAM_BINARY_FORMATS_OES: { *type = GL_INT; *numParams = 1; @@ -1360,28 +1311,29 @@ bool Context::getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned // Applies the render target surface, depth stencil surface, viewport rectangle and // scissor rectangle to the renderer -bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport) +Error Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport) { Framebuffer *framebufferObject = mState.getDrawFramebuffer(); ASSERT(framebufferObject && framebufferObject->completeness() == GL_FRAMEBUFFER_COMPLETE); - mRenderer->applyRenderTarget(framebufferObject); + gl::Error error = mRenderer->applyRenderTarget(framebufferObject); + if (error.isError()) + { + return error; + } float nearZ, farZ; mState.getDepthRange(&nearZ, &farZ); - if (!mRenderer->setViewport(mState.getViewport(), nearZ, farZ, drawMode, mState.getRasterizerState().frontFace, - ignoreViewport)) - { - return false; - } + mRenderer->setViewport(mState.getViewport(), nearZ, farZ, drawMode, mState.getRasterizerState().frontFace, + ignoreViewport); mRenderer->setScissorRectangle(mState.getScissor(), mState.isScissorTestEnabled()); - return true; + return gl::Error(GL_NO_ERROR); } // Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device -void Context::applyState(GLenum drawMode) +Error Context::applyState(GLenum drawMode) { Framebuffer *framebufferObject = mState.getDrawFramebuffer(); int samples = framebufferObject->getSamples(); @@ -1390,7 +1342,11 @@ void Context::applyState(GLenum drawMode) rasterizer.pointDrawMode = (drawMode == GL_POINTS); rasterizer.multiSample = (samples != 0); - mRenderer->setRasterizerState(rasterizer); + Error error = mRenderer->setRasterizerState(rasterizer); + if (error.isError()) + { + return error; + } unsigned int mask = 0; if (mState.isSampleCoverageEnabled()) @@ -1400,7 +1356,6 @@ void Context::applyState(GLenum drawMode) mState.getSampleCoverageParams(&coverageValue, &coverageInvert); if (coverageValue != 0) { - float threshold = 0.5f; for (int i = 0; i < samples; ++i) @@ -1424,117 +1379,185 @@ void Context::applyState(GLenum drawMode) { mask = 0xFFFFFFFF; } - mRenderer->setBlendState(framebufferObject, mState.getBlendState(), mState.getBlendColor(), mask); + error = mRenderer->setBlendState(framebufferObject, mState.getBlendState(), mState.getBlendColor(), mask); + if (error.isError()) + { + return error; + } + + error = mRenderer->setDepthStencilState(mState.getDepthStencilState(), mState.getStencilRef(), mState.getStencilBackRef(), + rasterizer.frontFace == GL_CCW); + if (error.isError()) + { + return error; + } - mRenderer->setDepthStencilState(mState.getDepthStencilState(), mState.getStencilRef(), mState.getStencilBackRef(), - rasterizer.frontFace == GL_CCW); + return Error(GL_NO_ERROR); } // Applies the shaders and shader constants to the Direct3D 9 device -void Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive) +Error Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive) { const VertexAttribute *vertexAttributes = mState.getVertexArray()->getVertexAttributes(); - VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]; + VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]; VertexFormat::GetInputLayout(inputLayout, programBinary, vertexAttributes, mState.getVertexAttribCurrentValues()); const Framebuffer *fbo = mState.getDrawFramebuffer(); - mRenderer->applyShaders(programBinary, inputLayout, fbo, mState.getRasterizerState().rasterizerDiscard, transformFeedbackActive); + Error error = mRenderer->applyShaders(programBinary, inputLayout, fbo, mState.getRasterizerState().rasterizerDiscard, transformFeedbackActive); + if (error.isError()) + { + return error; + } - programBinary->applyUniforms(); + return programBinary->applyUniforms(); } -size_t Context::getCurrentTexturesAndSamplerStates(ProgramBinary *programBinary, SamplerType type, Texture **outTextures, - TextureType *outTextureTypes, SamplerState *outSamplers) +Error Context::generateSwizzles(ProgramBinary *programBinary, SamplerType type) { size_t samplerRange = programBinary->getUsedSamplerRange(type); + for (size_t i = 0; i < samplerRange; i++) { - outTextureTypes[i] = programBinary->getSamplerTextureType(type, i); - GLint textureUnit = programBinary->getSamplerMapping(type, i); // OpenGL texture image unit index + GLenum textureType = programBinary->getSamplerTextureType(type, i); + GLint textureUnit = programBinary->getSamplerMapping(type, i, getCaps()); if (textureUnit != -1) { - outTextures[i] = getSamplerTexture(textureUnit, outTextureTypes[i]); - outTextures[i]->getSamplerStateWithNativeOffset(&outSamplers[i]); - Sampler *samplerObject = mState.getSampler(textureUnit); - if (samplerObject) + Texture* texture = getSamplerTexture(textureUnit, textureType); + if (texture->getSamplerState().swizzleRequired()) { - samplerObject->getState(&outSamplers[i]); + Error error = mRenderer->generateSwizzle(texture); + if (error.isError()) + { + return error; + } } } - else - { - outTextures[i] = NULL; - } } - return samplerRange; + return Error(GL_NO_ERROR); } -void Context::generateSwizzles(Texture *textures[], size_t count) +Error Context::generateSwizzles(ProgramBinary *programBinary) { - for (size_t i = 0; i < count; i++) + Error error = generateSwizzles(programBinary, SAMPLER_VERTEX); + if (error.isError()) { - if (textures[i] && textures[i]->getSamplerState().swizzleRequired()) - { - mRenderer->generateSwizzle(textures[i]); - } + return error; } + + error = generateSwizzles(programBinary, SAMPLER_PIXEL); + if (error.isError()) + { + return error; + } + + return Error(GL_NO_ERROR); } // 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). -void Context::applyTextures(SamplerType shaderType, Texture *textures[], TextureType *textureTypes, SamplerState *samplers, - size_t textureCount, const FramebufferTextureSerialArray& framebufferSerials, - size_t framebufferSerialCount) +Error Context::applyTextures(ProgramBinary *programBinary, SamplerType shaderType, + const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount) { - // Range of Direct3D samplers of given sampler type - size_t samplerCount = (shaderType == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS - : mRenderer->getMaxVertexTextureImageUnits(); - - for (size_t samplerIndex = 0; samplerIndex < textureCount; samplerIndex++) + size_t samplerRange = programBinary->getUsedSamplerRange(shaderType); + for (size_t samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) { - Texture *texture = textures[samplerIndex]; - const SamplerState &sampler = samplers[samplerIndex]; - TextureType textureType = textureTypes[samplerIndex]; - - if (texture) + GLenum textureType = programBinary->getSamplerTextureType(shaderType, samplerIndex); + GLint textureUnit = programBinary->getSamplerMapping(shaderType, samplerIndex, getCaps()); + if (textureUnit != -1) { + SamplerState sampler; + Texture* texture = getSamplerTexture(textureUnit, textureType); + texture->getSamplerStateWithNativeOffset(&sampler); + + Sampler *samplerObject = mState.getSampler(textureUnit); + if (samplerObject) + { + samplerObject->getState(&sampler); + } + // TODO: std::binary_search may become unavailable using older versions of GCC - if (texture->isSamplerComplete(sampler) && + if (texture->isSamplerComplete(sampler, mTextureCaps, mExtensions, mClientVersion) && !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial())) { - mRenderer->setSamplerState(shaderType, samplerIndex, sampler); - mRenderer->setTexture(shaderType, samplerIndex, texture); - texture->resetDirty(); + Error error = mRenderer->setSamplerState(shaderType, samplerIndex, sampler); + if (error.isError()) + { + return error; + } + + error = mRenderer->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. Texture *incompleteTexture = getIncompleteTexture(textureType); - mRenderer->setTexture(shaderType, samplerIndex, incompleteTexture); - incompleteTexture->resetDirty(); + gl::Error error = mRenderer->setTexture(shaderType, samplerIndex, incompleteTexture); + if (error.isError()) + { + return error; + } } } else { - mRenderer->setTexture(shaderType, samplerIndex, NULL); + // No texture bound to this slot even though it is used by the shader, bind a NULL texture + Error error = mRenderer->setTexture(shaderType, samplerIndex, NULL); + if (error.isError()) + { + return error; + } } } - for (size_t samplerIndex = textureCount; samplerIndex < samplerCount; samplerIndex++) + // Set all the remaining textures to NULL + size_t samplerCount = (shaderType == SAMPLER_PIXEL) ? mCaps.maxTextureImageUnits + : mCaps.maxVertexTextureImageUnits; + for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++) { - mRenderer->setTexture(shaderType, samplerIndex, NULL); + Error error = mRenderer->setTexture(shaderType, samplerIndex, NULL); + if (error.isError()) + { + return error; + } } + + return Error(GL_NO_ERROR); } -bool Context::applyUniformBuffers() +Error Context::applyTextures(ProgramBinary *programBinary) +{ + FramebufferTextureSerialArray framebufferSerials; + size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&framebufferSerials); + + Error error = applyTextures(programBinary, SAMPLER_VERTEX, framebufferSerials, framebufferSerialCount); + if (error.isError()) + { + return error; + } + + error = applyTextures(programBinary, SAMPLER_PIXEL, framebufferSerials, framebufferSerialCount); + if (error.isError()) + { + return error; + } + + return Error(GL_NO_ERROR); +} + +Error Context::applyUniformBuffers() { Program *programObject = getProgram(mState.getCurrentProgramId()); ProgramBinary *programBinary = programObject->getProgramBinary(); - std::vector boundBuffers; + std::vector boundBuffers; for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < programBinary->getActiveUniformBlockCount(); uniformBlockIndex++) { @@ -1543,7 +1566,7 @@ bool Context::applyUniformBuffers() if (mState.getIndexedUniformBuffer(blockBinding)->id() == 0) { // undefined behaviour - return false; + return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer."); } else { @@ -1553,7 +1576,7 @@ bool Context::applyUniformBuffers() } } - return programBinary->applyUniformBuffers(boundBuffers); + return programBinary->applyUniformBuffers(boundBuffers, getCaps()); } bool Context::applyTransformFeedbackBuffers() @@ -1589,28 +1612,25 @@ void Context::markTransformFeedbackUsage() } } -void Context::clear(GLbitfield mask) +Error Context::clear(GLbitfield mask) { if (mState.isRasterizerDiscardEnabled()) { - return; + return Error(GL_NO_ERROR); } ClearParameters clearParams = mState.getClearParameters(mask); - if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport - { - return; - } + applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } -void Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values) +Error Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values) { if (mState.isRasterizerDiscardEnabled()) { - return; + return Error(GL_NO_ERROR); } // glClearBufferfv can be called to clear the color buffer or depth buffer @@ -1632,19 +1652,16 @@ void Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values) clearParams.depthClearValue = values[0]; } - if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport - { - return; - } + applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } -void Context::clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values) +Error Context::clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values) { if (mState.isRasterizerDiscardEnabled()) { - return; + return Error(GL_NO_ERROR); } // glClearBufferuv can only be called to clear a color buffer @@ -1656,19 +1673,16 @@ void Context::clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int * clearParams.colorUIClearValue = ColorUI(values[0], values[1], values[2], values[3]); clearParams.colorClearType = GL_UNSIGNED_INT; - if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport - { - return; - } + applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } -void Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values) +Error Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values) { if (mState.isRasterizerDiscardEnabled()) { - return; + return Error(GL_NO_ERROR); } // glClearBufferfv can be called to clear the color buffer or stencil buffer @@ -1690,19 +1704,16 @@ void Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values) clearParams.stencilClearValue = values[1]; } - if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport - { - return; - } + applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } -void Context::clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil) +Error Context::clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil) { if (mState.isRasterizerDiscardEnabled()) { - return; + return Error(GL_NO_ERROR); } // glClearBufferfi can only be called to clear a depth stencil buffer @@ -1712,135 +1723,145 @@ void Context::clearBufferfi(GLenum buffer, int drawbuffer, float depth, int sten clearParams.clearStencil = true; clearParams.stencilClearValue = stencil; - if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport - { - return; - } + applyRenderTarget(GL_TRIANGLES, true); // Clips the clear to the scissor rectangle but not the viewport - mRenderer->clear(clearParams, mState.getDrawFramebuffer()); + return mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } -void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, void* pixels) +Error Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLsizei *bufSize, void* pixels) { - gl::Framebuffer *framebuffer = mState.getReadFramebuffer(); + Framebuffer *framebuffer = mState.getReadFramebuffer(); - bool isSized = IsSizedInternalFormat(format); - GLenum sizedInternalFormat = (isSized ? format : GetSizedInternalFormat(format, type)); - GLuint outputPitch = GetRowPitch(sizedInternalFormat, type, width, mState.getPackAlignment()); + GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); + const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat); + GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, width, mState.getPackAlignment()); - mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, mState.getPackState(), pixels); + return mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, mState.getPackState(), + reinterpret_cast(pixels)); } -void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances) +Error Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances) { ASSERT(mState.getCurrentProgramId() != 0); ProgramBinary *programBinary = mState.getCurrentProgramBinary(); programBinary->updateSamplerMapping(); - Texture *vsTextures[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - TextureType vsTextureTypes[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - SamplerState vsSamplers[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - size_t vsTextureCount = getCurrentTexturesAndSamplerStates(programBinary, SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers); - - Texture *psTextures[MAX_TEXTURE_IMAGE_UNITS]; - TextureType psTextureTypes[MAX_TEXTURE_IMAGE_UNITS]; - SamplerState psSamplers[MAX_TEXTURE_IMAGE_UNITS]; - size_t psTextureCount = getCurrentTexturesAndSamplerStates(programBinary, SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers); - - generateSwizzles(vsTextures, vsTextureCount); - generateSwizzles(psTextures, psTextureCount); + Error error = generateSwizzles(programBinary); + if (error.isError()) + { + return error; + } if (!mRenderer->applyPrimitiveType(mode, count)) { - return; + return Error(GL_NO_ERROR); } - if (!applyRenderTarget(mode, false)) + error = applyRenderTarget(mode, false); + if (error.isError()) { - return; + return error; } - applyState(mode); + error = applyState(mode); + if (error.isError()) + { + return error; + } - GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.getVertexArray()->getVertexAttributes(), mState.getVertexAttribCurrentValues(), first, count, instances); - if (err != GL_NO_ERROR) + error = mRenderer->applyVertexBuffer(programBinary, mState.getVertexArray()->getVertexAttributes(), mState.getVertexAttribCurrentValues(), first, count, instances); + if (error.isError()) { - return gl::error(err); + return error; } bool transformFeedbackActive = applyTransformFeedbackBuffers(); - applyShaders(programBinary, transformFeedbackActive); - - FramebufferTextureSerialArray frameBufferSerials; - size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&frameBufferSerials); + error = applyShaders(programBinary, transformFeedbackActive); + if (error.isError()) + { + return error; + } - applyTextures(SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers, vsTextureCount, frameBufferSerials, framebufferSerialCount); - applyTextures(SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers, psTextureCount, frameBufferSerials, framebufferSerialCount); + error = applyTextures(programBinary); + if (error.isError()) + { + return error; + } - if (!applyUniformBuffers()) + error = applyUniformBuffers(); + if (error.isError()) { - return; + return error; } if (!skipDraw(mode)) { - mRenderer->drawArrays(mode, count, instances, transformFeedbackActive); + error = mRenderer->drawArrays(mode, count, instances, transformFeedbackActive); + if (error.isError()) + { + return error; + } if (transformFeedbackActive) { markTransformFeedbackUsage(); } } + + return gl::Error(GL_NO_ERROR); } -void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances) +Error Context::drawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei instances, + const rx::RangeUI &indexRange) { ASSERT(mState.getCurrentProgramId() != 0); ProgramBinary *programBinary = mState.getCurrentProgramBinary(); programBinary->updateSamplerMapping(); - Texture *vsTextures[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - TextureType vsTextureTypes[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - SamplerState vsSamplers[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - size_t vsTextureCount = getCurrentTexturesAndSamplerStates(programBinary, SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers); - - Texture *psTextures[MAX_TEXTURE_IMAGE_UNITS]; - TextureType psTextureTypes[MAX_TEXTURE_IMAGE_UNITS]; - SamplerState psSamplers[MAX_TEXTURE_IMAGE_UNITS]; - size_t psTextureCount = getCurrentTexturesAndSamplerStates(programBinary, SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers); - - generateSwizzles(vsTextures, vsTextureCount); - generateSwizzles(psTextures, psTextureCount); + Error error = generateSwizzles(programBinary); + if (error.isError()) + { + return error; + } if (!mRenderer->applyPrimitiveType(mode, count)) { - return; + return Error(GL_NO_ERROR); } - if (!applyRenderTarget(mode, false)) + error = applyRenderTarget(mode, false); + if (error.isError()) { - return; + return error; } - applyState(mode); + error = applyState(mode); + if (error.isError()) + { + return error; + } VertexArray *vao = mState.getVertexArray(); rx::TranslatedIndexData indexInfo; - GLenum err = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo); - if (err != GL_NO_ERROR) + indexInfo.indexRange = indexRange; + error = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo); + if (error.isError()) { - return gl::error(err); + return error; } - GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; - err = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(), mState.getVertexAttribCurrentValues(), indexInfo.minIndex, vertexCount, instances); - if (err != GL_NO_ERROR) + GLsizei vertexCount = indexInfo.indexRange.length() + 1; + error = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(), + mState.getVertexAttribCurrentValues(), + indexInfo.indexRange.start, vertexCount, instances); + if (error.isError()) { - return gl::error(err); + return error; } bool transformFeedbackActive = applyTransformFeedbackBuffers(); @@ -1848,23 +1869,34 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid // layer. ASSERT(!transformFeedbackActive); - applyShaders(programBinary, transformFeedbackActive); - - FramebufferTextureSerialArray frameBufferSerials; - size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&frameBufferSerials); + error = applyShaders(programBinary, transformFeedbackActive); + if (error.isError()) + { + return error; + } - applyTextures(SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers, vsTextureCount, frameBufferSerials, framebufferSerialCount); - applyTextures(SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers, psTextureCount, frameBufferSerials, framebufferSerialCount); + error = applyTextures(programBinary); + if (error.isError()) + { + return error; + } - if (!applyUniformBuffers()) + error = applyUniformBuffers(); + if (error.isError()) { - return; + return error; } if (!skipDraw(mode)) { - mRenderer->drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances); + error = mRenderer->drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances); + if (error.isError()) + { + return error; + } } + + return Error(GL_NO_ERROR); } // Implements glFlush when block is false, glFinish when block is true @@ -1873,71 +1905,28 @@ void Context::sync(bool block) mRenderer->sync(block); } -void Context::recordInvalidEnum() -{ - mInvalidEnum = true; -} - -void Context::recordInvalidValue() -{ - mInvalidValue = true; -} - -void Context::recordInvalidOperation() -{ - mInvalidOperation = true; -} - -void Context::recordOutOfMemory() +void Context::recordError(const Error &error) { - mOutOfMemory = true; -} - -void Context::recordInvalidFramebufferOperation() -{ - mInvalidFramebufferOperation = true; + 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 (mInvalidEnum) - { - mInvalidEnum = false; - - return GL_INVALID_ENUM; - } - - if (mInvalidValue) + if (mErrors.empty()) { - mInvalidValue = false; - - return GL_INVALID_VALUE; - } - - if (mInvalidOperation) - { - mInvalidOperation = false; - - return GL_INVALID_OPERATION; - } - - if (mOutOfMemory) - { - mOutOfMemory = false; - - return GL_OUT_OF_MEMORY; + return GL_NO_ERROR; } - - if (mInvalidFramebufferOperation) + else { - mInvalidFramebufferOperation = false; - - return GL_INVALID_FRAMEBUFFER_OPERATION; + GLenum error = *mErrors.begin(); + mErrors.erase(mErrors.begin()); + return error; } - - return GL_NO_ERROR; } GLenum Context::getResetStatus() @@ -1989,53 +1978,6 @@ const Extensions &Context::getExtensions() const return mExtensions; } -int Context::getMajorShaderModel() const -{ - return mMajorShaderModel; -} - -unsigned int Context::getMaximumCombinedTextureImageUnits() const -{ - return mRenderer->getMaxCombinedTextureImageUnits(); -} - -unsigned int Context::getMaximumCombinedUniformBufferBindings() const -{ - return mRenderer->getMaxVertexShaderUniformBuffers() + - mRenderer->getMaxFragmentShaderUniformBuffers(); -} - -int Context::getMaxSupportedSamples() const -{ - return mRenderer->getMaxSupportedSamples(); -} - -GLsizei Context::getMaxSupportedFormatSamples(GLenum internalFormat) const -{ - return mRenderer->getMaxSupportedFormatSamples(internalFormat); -} - -GLsizei Context::getNumSampleCounts(GLenum internalFormat) const -{ - return mRenderer->getNumSampleCounts(internalFormat); -} - -void Context::getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const -{ - mRenderer->getSampleCounts(internalFormat, bufSize, params); -} - -unsigned int Context::getMaxTransformFeedbackBufferBindings() const -{ - return mRenderer->getMaxTransformFeedbackBuffers(); -} - -GLintptr Context::getUniformBufferOffsetAlignment() const -{ - // setting a large alignment forces uniform buffers to bind with zero offset - return static_cast(std::numeric_limits::max()); -} - void Context::getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type) { Framebuffer *framebuffer = mState.getReadFramebuffer(); @@ -2044,9 +1986,12 @@ void Context::getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, G FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); ASSERT(attachment); - *internalFormat = attachment->getActualFormat(); - *format = gl::GetFormat(attachment->getActualFormat()); - *type = gl::GetType(attachment->getActualFormat()); + GLenum actualFormat = attachment->getActualFormat(); + const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualFormat); + + *internalFormat = actualFormat; + *format = actualFormatInfo.format; + *type = actualFormatInfo.type; } void Context::detachTexture(GLuint texture) @@ -2127,32 +2072,31 @@ void Context::detachSampler(GLuint sampler) mState.detachSampler(sampler); } -Texture *Context::getIncompleteTexture(TextureType type) +Texture *Context::getIncompleteTexture(GLenum type) { - Texture *t = mIncompleteTextures[type].get(); - - if (t == NULL) + if (mIncompleteTextures.find(type) == mIncompleteTextures.end()) { const GLubyte color[] = { 0, 0, 0, 255 }; const PixelUnpackState incompleteUnpackState(1); + Texture* t = NULL; switch (type) { default: UNREACHABLE(); // default falls through to TEXTURE_2D - case TEXTURE_2D: + case GL_TEXTURE_2D: { - Texture2D *incomplete2d = new Texture2D(mRenderer->createTexture2D(), Texture::INCOMPLETE_TEXTURE_ID); + Texture2D *incomplete2d = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), Texture::INCOMPLETE_TEXTURE_ID); incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); t = incomplete2d; } break; - case TEXTURE_CUBE: + case GL_TEXTURE_CUBE_MAP: { - TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer->createTextureCube(), Texture::INCOMPLETE_TEXTURE_ID); + TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), Texture::INCOMPLETE_TEXTURE_ID); incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); @@ -2165,18 +2109,18 @@ Texture *Context::getIncompleteTexture(TextureType type) } break; - case TEXTURE_3D: + case GL_TEXTURE_3D: { - Texture3D *incomplete3d = new Texture3D(mRenderer->createTexture3D(), Texture::INCOMPLETE_TEXTURE_ID); + Texture3D *incomplete3d = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), Texture::INCOMPLETE_TEXTURE_ID); incomplete3d->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); t = incomplete3d; } break; - case TEXTURE_2D_ARRAY: + case GL_TEXTURE_2D_ARRAY: { - Texture2DArray *incomplete2darray = new Texture2DArray(mRenderer->createTexture2DArray(), Texture::INCOMPLETE_TEXTURE_ID); + Texture2DArray *incomplete2darray = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), Texture::INCOMPLETE_TEXTURE_ID); incomplete2darray->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); t = incomplete2darray; @@ -2187,7 +2131,7 @@ Texture *Context::getIncompleteTexture(TextureType type) mIncompleteTextures[type].set(t); } - return t; + return mIncompleteTextures[type].get(); } bool Context::skipDraw(GLenum drawMode) @@ -2359,14 +2303,16 @@ size_t Context::getBoundFramebufferTextureSerials(FramebufferTextureSerialArray FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i); if (attachment && attachment->isTexture()) { - (*outSerialArray)[serialCount++] = attachment->getTextureSerial(); + Texture *texture = attachment->getTexture(); + (*outSerialArray)[serialCount++] = texture->getTextureSerial(); } } FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer(); if (depthStencilAttachment && depthStencilAttachment->isTexture()) { - (*outSerialArray)[serialCount++] = depthStencilAttachment->getTextureSerial(); + Texture *depthStencilTexture = depthStencilAttachment->getTexture(); + (*outSerialArray)[serialCount++] = depthStencilTexture->getTextureSerial(); } std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount); @@ -2396,114 +2342,19 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 blitDepth = true; } - gl::Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0); - gl::Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); + Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0); + Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); if (blitRenderTarget || blitDepth || blitStencil) { - const gl::Rectangle *scissor = mState.isScissorTestEnabled() ? &mState.getScissor() : NULL; + const Rectangle *scissor = mState.isScissorTestEnabled() ? &mState.getScissor() : NULL; mRenderer->blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor, blitRenderTarget, blitDepth, blitStencil, filter); } } -void Context::invalidateFrameBuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, - GLint x, GLint y, GLsizei width, GLsizei height) -{ - Framebuffer *frameBuffer = NULL; - switch (target) - { - case GL_FRAMEBUFFER: - case GL_DRAW_FRAMEBUFFER: - frameBuffer = mState.getDrawFramebuffer(); - break; - case GL_READ_FRAMEBUFFER: - frameBuffer = mState.getReadFramebuffer(); - break; - default: - UNREACHABLE(); - } - - if (frameBuffer && frameBuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) - { - for (int i = 0; i < numAttachments; ++i) - { - rx::RenderTarget *renderTarget = NULL; - - if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) - { - gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(attachments[i] - GL_COLOR_ATTACHMENT0); - if (attachment) - { - renderTarget = attachment->getRenderTarget(); - } - } - else if (attachments[i] == GL_COLOR) - { - gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(0); - if (attachment) - { - renderTarget = attachment->getRenderTarget(); - } - } - else - { - gl::FramebufferAttachment *attachment = NULL; - switch (attachments[i]) - { - case GL_DEPTH_ATTACHMENT: - case GL_DEPTH: - attachment = frameBuffer->getDepthbuffer(); - break; - case GL_STENCIL_ATTACHMENT: - case GL_STENCIL: - attachment = frameBuffer->getStencilbuffer(); - break; - case GL_DEPTH_STENCIL_ATTACHMENT: - attachment = frameBuffer->getDepthOrStencilbuffer(); - break; - default: - UNREACHABLE(); - } - - if (attachment) - { - renderTarget = attachment->getDepthStencil(); - } - } - - if (renderTarget) - { - renderTarget->invalidate(x, y, width, height); - } - } - } -} - -bool Context::hasMappedBuffer(GLenum target) const +void Context::releaseShaderCompiler() { - if (target == GL_ARRAY_BUFFER) - { - for (unsigned int attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; attribIndex++) - { - const gl::VertexAttribute &vertexAttrib = mState.getVertexAttribState(attribIndex); - gl::Buffer *boundBuffer = vertexAttrib.buffer.get(); - if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped()) - { - return true; - } - } - } - else if (target == GL_ELEMENT_ARRAY_BUFFER) - { - Buffer *elementBuffer = mState.getTargetBuffer(target); - return (elementBuffer && elementBuffer->isMapped()); - } - else if (target == GL_TRANSFORM_FEEDBACK_BUFFER) - { - UNIMPLEMENTED(); - } - else UNREACHABLE(); - return false; + mRenderer->releaseShaderCompiler(); } void Context::initCaps(GLuint clientVersion) @@ -2524,20 +2375,45 @@ void Context::initCaps(GLuint clientVersion) //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; - if (formatCaps.texturable && IsValidInternalFormat(format, mExtensions, clientVersion)) + 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) { - // Update the format caps based on the client version and extensions - formatCaps.renderable = IsRenderingSupported(format, mExtensions, clientVersion); - formatCaps.filterable = IsFilteringSupported(format, mExtensions, clientVersion); - mTextureCaps.insert(format, formatCaps); + mCaps.compressedTextureFormats.push_back(format); } + + mTextureCaps.insert(format, formatCaps); } + + mExtensions.maxSamples = maxSamples; } } diff --git a/src/3rdparty/angle/src/libGLESv2/Context.h b/src/3rdparty/angle/src/libGLESv2/Context.h index 6c93c74e79..1b888aec83 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.h +++ b/src/3rdparty/angle/src/libGLESv2/Context.h @@ -10,23 +10,24 @@ #ifndef LIBGLESV2_CONTEXT_H_ #define LIBGLESV2_CONTEXT_H_ -#include "angle_gl.h" - -#include -#include -#include -#include -#include - #include "common/angleutils.h" #include "common/RefCountObject.h" #include "libGLESv2/Caps.h" +#include "libGLESv2/Error.h" #include "libGLESv2/HandleAllocator.h" #include "libGLESv2/angletypes.h" #include "libGLESv2/Constants.h" #include "libGLESv2/VertexAttribute.h" #include "libGLESv2/State.h" +#include "angle_gl.h" + +#include +#include +#include +#include +#include + namespace rx { class Renderer; @@ -114,10 +115,7 @@ class Context void bindArrayBuffer(GLuint buffer); void bindElementArrayBuffer(GLuint buffer); - void bindTexture2D(GLuint texture); - void bindTextureCubeMap(GLuint texture); - void bindTexture3D(GLuint texture); - void bindTexture2DArray(GLuint texture); + void bindTexture(GLenum target, GLuint texture); void bindReadFramebuffer(GLuint framebuffer); void bindDrawFramebuffer(GLuint framebuffer); void bindRenderbuffer(GLuint renderbuffer); @@ -133,11 +131,11 @@ class Context void bindPixelUnpackBuffer(GLuint buffer); void useProgram(GLuint program); void linkProgram(GLuint program); - void setProgramBinary(GLuint program, const void *binary, GLint length); + void setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length); void bindTransformFeedback(GLuint transformFeedback); - void beginQuery(GLenum target, GLuint query); - void endQuery(GLenum target); + Error beginQuery(GLenum target, GLuint query); + Error endQuery(GLenum target); void setFramebufferZero(Framebuffer *framebuffer); @@ -169,7 +167,7 @@ class Context Texture3D *getTexture3D() const; Texture2DArray *getTexture2DArray() const; - Texture *getSamplerTexture(unsigned int sampler, TextureType type) const; + Texture *getSamplerTexture(unsigned int sampler, GLenum type) const; bool isSampler(GLuint samplerName) const; @@ -184,22 +182,20 @@ class Context bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams); bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams); - void clear(GLbitfield mask); - void clearBufferfv(GLenum buffer, int drawbuffer, const float *values); - void clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values); - void clearBufferiv(GLenum buffer, int drawbuffer, const int *values); - void clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil); - - void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels); - void drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances); - void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances); + Error clear(GLbitfield mask); + Error clearBufferfv(GLenum buffer, int drawbuffer, const float *values); + Error clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values); + Error clearBufferiv(GLenum buffer, int drawbuffer, const int *values); + Error clearBufferfi(GLenum buffer, int drawbuffer, float depth, int 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); void sync(bool block); // flush/finish - void recordInvalidEnum(); - void recordInvalidValue(); - void recordInvalidOperation(); - void recordOutOfMemory(); - void recordInvalidFramebufferOperation(); + void recordError(const Error &error); GLenum getError(); GLenum getResetStatus(); @@ -211,15 +207,6 @@ class Context const TextureCapsMap &getTextureCaps() const; const Extensions &getExtensions() const; - int getMajorShaderModel() const; - unsigned int getMaximumCombinedTextureImageUnits() const; - unsigned int getMaximumCombinedUniformBufferBindings() const; - GLsizei getMaxSupportedSamples() const; - GLsizei getMaxSupportedFormatSamples(GLenum internalFormat) const; - GLsizei getNumSampleCounts(GLenum internalFormat) const; - void getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const; - unsigned int getMaxTransformFeedbackBufferBindings() const; - GLintptr getUniformBufferOffsetAlignment() const; const std::string &getRendererString() const; const std::string &getExtensionString() const; @@ -231,29 +218,26 @@ class Context void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); - void invalidateFrameBuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, - GLint x, GLint y, GLsizei width, GLsizei height); - - bool hasMappedBuffer(GLenum target) const; - rx::Renderer *getRenderer() { return mRenderer; } State &getState() { return mState; } const State &getState() const { return mState; } + void releaseShaderCompiler(); + private: DISALLOW_COPY_AND_ASSIGN(Context); // TODO: std::array may become unavailable using older versions of GCC typedef std::array FramebufferTextureSerialArray; - bool applyRenderTarget(GLenum drawMode, bool ignoreViewport); - void applyState(GLenum drawMode); - void applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive); - void applyTextures(SamplerType shaderType, Texture *textures[], TextureType *textureTypes, SamplerState *samplers, - size_t textureCount, const FramebufferTextureSerialArray& framebufferSerials, - size_t framebufferSerialCount); - bool applyUniformBuffers(); + Error applyRenderTarget(GLenum drawMode, bool ignoreViewport); + Error applyState(GLenum drawMode); + Error applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive); + Error applyTextures(ProgramBinary *programBinary, SamplerType shaderType, const FramebufferTextureSerialArray &framebufferSerials, + size_t framebufferSerialCount); + Error applyTextures(ProgramBinary *programBinary); + Error applyUniformBuffers(); bool applyTransformFeedbackBuffers(); void markTransformFeedbackUsage(); @@ -265,10 +249,10 @@ class Context void detachTransformFeedback(GLuint transformFeedback); void detachSampler(GLuint sampler); - void generateSwizzles(Texture *textures[], size_t count); - size_t getCurrentTexturesAndSamplerStates(ProgramBinary *programBinary, SamplerType type, Texture **outTextures, - TextureType *outTextureTypes, SamplerState *outSamplers); - Texture *getIncompleteTexture(TextureType type); + Error generateSwizzles(ProgramBinary *programBinary, SamplerType type); + Error generateSwizzles(ProgramBinary *programBinary); + + Texture *getIncompleteTexture(GLenum type); bool skipDraw(GLenum drawMode); @@ -289,10 +273,9 @@ class Context int mClientVersion; - BindingPointer mTexture2DZero; - BindingPointer mTextureCubeMapZero; - BindingPointer mTexture3DZero; - BindingPointer mTexture2DArrayZero; + typedef std::map< GLenum, BindingPointer > TextureMap; + TextureMap mZeroTextures; + TextureMap mIncompleteTextures; typedef std::unordered_map FramebufferMap; FramebufferMap mFramebufferMap; @@ -319,14 +302,9 @@ class Context std::string mExtensionString; std::vector mExtensionStrings; - BindingPointer mIncompleteTextures[TEXTURE_TYPE_COUNT]; - // Recorded errors - bool mInvalidEnum; - bool mInvalidValue; - bool mInvalidOperation; - bool mOutOfMemory; - bool mInvalidFramebufferOperation; + typedef std::set ErrorSet; + ErrorSet mErrors; // Current/lost context flags bool mHasBeenCurrent; @@ -335,10 +313,6 @@ class Context GLenum mResetStrategy; bool mRobustAccess; - int mMajorShaderModel; - bool mSupportsVertexTexture; - int mNumCompressedTextureFormats; - ResourceManager *mResourceManager; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/DynamicHLSL.cpp b/src/3rdparty/angle/src/libGLESv2/DynamicHLSL.cpp deleted file mode 100644 index e3ec391bfa..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/DynamicHLSL.cpp +++ /dev/null @@ -1,1122 +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 "precompiled.h" - -#include "libGLESv2/DynamicHLSL.h" -#include "libGLESv2/Shader.h" -#include "libGLESv2/Program.h" -#include "libGLESv2/renderer/Renderer.h" -#include "common/utilities.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/formatutils.h" -#include "common/blocklayout.h" - -// For use with ArrayString, see angleutils.h -META_ASSERT(GL_INVALID_INDEX == UINT_MAX); - -namespace gl_d3d -{ - -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)); -} - -} - -namespace gl -{ - -const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@"; -const std::string PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@"; - -DynamicHLSL::DynamicHLSL(rx::Renderer *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; - - 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; - - 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[x] < space[column]) - { - column = x; - } - } - - if (space[column] >= registers) - { - for (int r = 0; r < maxVaryingVectors; r++) - { - if (!packing[r][column]) - { - varying->registerIndex = r; - - 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, FragmentShader *fragmentShader, - VertexShader *vertexShader, const std::vector& transformFeedbackVaryings) -{ - const int maxVaryingVectors = mRenderer->getMaxVaryingVectors(); - - vertexShader->resetVaryingsRegisterAssignment(); - fragmentShader->resetVaryingsRegisterAssignment(); - - std::set packedVaryings; - - for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++) - { - PackedVarying *varying = &fragmentShader->mVaryings[varyingIndex]; - 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 (packedVaryings.find(transformFeedbackVarying) == packedVaryings.end()) - { - bool found = false; - for (unsigned int varyingIndex = 0; varyingIndex < vertexShader->mVaryings.size(); varyingIndex++) - { - PackedVarying *varying = &vertexShader->mVaryings[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 && transformFeedbackVarying != "gl_Position" && transformFeedbackVarying != "gl_PointSize") - { - 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(VertexShader *shader) const -{ - std::string varyingSemantic = getVaryingSemantic(shader->mUsesPointSize); - std::string varyingHLSL; - - for (unsigned int varyingIndex = 0; varyingIndex < shader->mVaryings.size(); varyingIndex++) - { - const PackedVarying &varying = shader->mVaryings[varyingIndex]; - if (varying.registerAssigned()) - { - 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++) - { - 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.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 = gl_d3d::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++) - { - ASSERT(inputIndex < MAX_VERTEX_ATTRIBS); - - const VertexFormat &vertexFormat = inputLayout[inputIndex]; - const sh::Attribute &shaderAttribute = shaderAttributes[attributeIndex]; - - if (!shaderAttribute.name.empty()) - { - // HLSL code for input structure - if (IsMatrixType(shaderAttribute.type)) - { - // Matrix types are always transposed - structHLSL += " " + gl_d3d::HLSLMatrixTypeString(TransposeMatrixType(shaderAttribute.type)); - } - else - { - GLenum componentType = mRenderer->getVertexComponentType(vertexFormat); - structHLSL += " " + gl_d3d::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) & rx::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 i = 0; i < outputVariables.size(); i++) - { - const PixelShaderOuputVariable& outputVariable = outputVariables[i]; - ASSERT(outputLayout.size() > outputVariable.outputIndex); - - // FIXME(geofflang): Work around NVIDIA driver bug by repacking buffers - bool outputIndexEnabled = true; // outputLayout[outputVariable.outputIndex] != GL_NONE - if (outputIndexEnabled) - { - declarationHLSL += " " + gl_d3d::HLSLTypeString(outputVariable.type) + " " + outputVariable.name + - " : " + targetSemantic + Str(outputVariable.outputIndex) + ";\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 VertexShader *vertexShader, - std::vector *linkedVaryings) const -{ - const std::string &varyingSemantic = getVaryingSemantic(vertexShader->mUsesPointSize); - const std::vector &varyings = vertexShader->mVaryings; - - for (unsigned int varyingIndex = 0; varyingIndex < varyings.size(); varyingIndex++) - { - const PackedVarying &varying = varyings[varyingIndex]; - if (varying.registerAssigned()) - { - 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(InfoLog &infoLog, int registers, const VaryingPacking packing, - std::string& pixelHLSL, std::string& vertexHLSL, - FragmentShader *fragmentShader, VertexShader *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 maxVaryingVectors = mRenderer->getMaxVaryingVectors(); - - 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 && mRenderer->getCurrentClientVersion() < 3); - const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getRendererCaps().maxDrawBuffers : 1); - - int shaderVersion = vertexShader->getShaderVersion(); - - if (registersNeeded > 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"; - } - - for (unsigned int vertVaryingIndex = 0; vertVaryingIndex < vertexShader->mVaryings.size(); vertVaryingIndex++) - { - const PackedVarying &varying = vertexShader->mVaryings[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 + elementIndex * variableRows + row; - vertexHLSL += " output.v" + Str(r); - - bool sharedRegister = false; // Register used by multiple varyings - - for (int x = 0; x < 4; x++) - { - if (packing[r][x] && packing[r][x] != packing[r][0]) - { - sharedRegister = true; - break; - } - } - - if(sharedRegister) - { - vertexHLSL += "."; - - for (int x = 0; x < 4; x++) - { - if (packing[r][x] == &varying) - { - switch(x) - { - case 0: vertexHLSL += "x"; break; - case 1: vertexHLSL += "y"; break; - case 2: vertexHLSL += "z"; break; - case 3: vertexHLSL += "w"; break; - } - } - } - } - - 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++) - { - PixelShaderOuputVariable 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->getOutputVariables(); - 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)); - - PixelShaderOuputVariable 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"; - } - } - - for (unsigned int varyingIndex = 0; varyingIndex < fragmentShader->mVaryings.size(); varyingIndex++) - { - const PackedVarying &varying = fragmentShader->mVaryings[varyingIndex]; - if (varying.registerAssigned()) - { - 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 + 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 UNREACHABLE(); - } - - pixelHLSL += "\n" - " gl_main();\n" - "\n" - " return generateOutput();\n" - "}\n"; - - return true; -} - -void DynamicHLSL::defineOutputVariables(FragmentShader *fragmentShader, std::map *programOutputVars) const -{ - const std::vector &shaderOutputVars = fragmentShader->getOutputVariables(); - - for (unsigned int outputVariableIndex = 0; outputVariableIndex < shaderOutputVars.size(); outputVariableIndex++) - { - const sh::Attribute &outputVariable = shaderOutputVars[outputVariableIndex]; - const int baseLocation = outputVariable.location == -1 ? 0 : outputVariable.location; - - 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, FragmentShader *fragmentShader, VertexShader *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, FragmentShader *fragmentShader, VertexShader *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) & rx::VERTEX_CONVERT_GPU) != 0); - signature[inputIndex] = (gpuConverted ? GL_TRUE : GL_FALSE); - } - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/DynamicHLSL.h b/src/3rdparty/angle/src/libGLESv2/DynamicHLSL.h deleted file mode 100644 index 68abd6e1a4..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/DynamicHLSL.h +++ /dev/null @@ -1,96 +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_DYNAMIC_HLSL_H_ -#define LIBGLESV2_DYNAMIC_HLSL_H_ - -#include "common/angleutils.h" -#include "libGLESv2/constants.h" - -namespace rx -{ -class Renderer; -} - -namespace sh -{ -struct Attribute; -struct ShaderVariable; -} - -namespace gl -{ - -class InfoLog; -class FragmentShader; -class VertexShader; -struct VariableLocation; -struct LinkedVarying; -struct VertexAttribute; -struct VertexFormat; -struct PackedVarying; - -typedef const PackedVarying *VaryingPacking[IMPLEMENTATION_MAX_VARYING_VECTORS][4]; - -struct PixelShaderOuputVariable -{ - GLenum type; - std::string name; - std::string source; - size_t outputIndex; -}; - -class DynamicHLSL -{ - public: - explicit DynamicHLSL(rx::Renderer *const renderer); - - int packVaryings(InfoLog &infoLog, VaryingPacking packing, FragmentShader *fragmentShader, - VertexShader *vertexShader, const std::vector& transformFeedbackVaryings); - std::string generateVertexShaderForInputLayout(const std::string &sourceShader, const 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(InfoLog &infoLog, int registers, const VaryingPacking packing, - std::string& pixelHLSL, std::string& vertexHLSL, - FragmentShader *fragmentShader, VertexShader *vertexShader, - const std::vector& transformFeedbackVaryings, - std::vector *linkedVaryings, - std::map *programOutputVars, - std::vector *outPixelShaderKey, - bool *outUsesFragDepth) const; - - std::string generateGeometryShaderHLSL(int registers, FragmentShader *fragmentShader, VertexShader *vertexShader) const; - void getInputLayoutSignature(const VertexFormat inputLayout[], GLenum signature[]) const; - - private: - DISALLOW_COPY_AND_ASSIGN(DynamicHLSL); - - rx::Renderer *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(VertexShader *shader) const; - void storeUserLinkedVaryings(const VertexShader *vertexShader, std::vector *linkedVaryings) const; - void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector *linkedVaryings) const; - void defineOutputVariables(FragmentShader *fragmentShader, std::map *programOutputVars) const; - std::string generatePointSpriteHLSL(int registers, FragmentShader *fragmentShader, VertexShader *vertexShader) const; - - // Prepend an underscore - static std::string decorateVariable(const std::string &name); - - std::string generateAttributeConversionHLSL(const VertexFormat &vertexFormat, const sh::ShaderVariable &shaderAttrib) const; -}; - -} - -#endif // LIBGLESV2_DYNAMIC_HLSL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Error.cpp b/src/3rdparty/angle/src/libGLESv2/Error.cpp new file mode 100644 index 0000000000..cc7d17eb37 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/Error.cpp @@ -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. +// + +// 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 new file mode 100644 index 0000000000..b70b5a531c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/Error.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. + +// 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 index 31d149d629..ee9a07a5c4 100644 --- a/src/3rdparty/angle/src/libGLESv2/Fence.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Fence.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -23,6 +22,8 @@ #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/main.h" +#include "angle_gl.h" + namespace gl { diff --git a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp index b90d2f6023..5bf7b3fce8 100644 --- a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp index f808175250..5b21433f90 100644 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -9,15 +8,60 @@ // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. #include "libGLESv2/Framebuffer.h" - #include "libGLESv2/main.h" -#include "common/utilities.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/Texture.h" #include "libGLESv2/Context.h" -#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/FramebufferAttachment.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/renderer/d3d/TextureD3D.h" + +#include "common/utilities.h" + +namespace rx +{ +RenderTarget *GetAttachmentRenderTarget(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->getRenderTarget(*index); + } + + gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer(); + ASSERT(renderbuffer); + + // TODO: cast to RenderbufferD3D + return renderbuffer->getStorage()->getRenderTarget(); +} + +// 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); + + // TODO: cast to RenderbufferD3D + return renderbuffer->getStorage()->getSerial(); +} + +} namespace gl { @@ -47,7 +91,7 @@ Framebuffer::~Framebuffer() SafeDelete(mStencilbuffer); } -FramebufferAttachment *Framebuffer::createAttachment(GLenum type, GLuint handle, GLint level, GLint layer) const +FramebufferAttachment *Framebuffer::createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const { if (handle == 0) { @@ -62,15 +106,14 @@ FramebufferAttachment *Framebuffer::createAttachment(GLenum type, GLuint handle, return NULL; case GL_RENDERBUFFER: - return new RenderbufferAttachment(context->getRenderbuffer(handle)); + return new RenderbufferAttachment(binding, context->getRenderbuffer(handle)); case GL_TEXTURE_2D: { Texture *texture = context->getTexture(handle); if (texture && texture->getTarget() == GL_TEXTURE_2D) { - Texture2D *tex2D = static_cast(texture); - return new Texture2DAttachment(tex2D, level); + return new TextureAttachment(binding, texture, ImageIndex::Make2D(level)); } else { @@ -88,8 +131,7 @@ FramebufferAttachment *Framebuffer::createAttachment(GLenum type, GLuint handle, Texture *texture = context->getTexture(handle); if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP) { - TextureCubeMap *texCube = static_cast(texture); - return new TextureCubeMapAttachment(texCube, type, level); + return new TextureAttachment(binding, texture, ImageIndex::MakeCube(type, level)); } else { @@ -102,8 +144,7 @@ FramebufferAttachment *Framebuffer::createAttachment(GLenum type, GLuint handle, Texture *texture = context->getTexture(handle); if (texture && texture->getTarget() == GL_TEXTURE_3D) { - Texture3D *tex3D = static_cast(texture); - return new Texture3DAttachment(tex3D, level, layer); + return new TextureAttachment(binding, texture, ImageIndex::Make3D(level, layer)); } else { @@ -116,8 +157,7 @@ FramebufferAttachment *Framebuffer::createAttachment(GLenum type, GLuint handle, Texture *texture = context->getTexture(handle); if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY) { - Texture2DArray *tex2DArray = static_cast(texture); - return new Texture2DArrayAttachment(tex2DArray, level, layer); + return new TextureAttachment(binding, texture, ImageIndex::Make2DArray(level, layer)); } else { @@ -135,24 +175,25 @@ void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLui { ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); SafeDelete(mColorbuffers[colorAttachment]); - mColorbuffers[colorAttachment] = createAttachment(type, colorbuffer, level, layer); + GLenum binding = colorAttachment + GL_COLOR_ATTACHMENT0; + mColorbuffers[colorAttachment] = createAttachment(binding, type, colorbuffer, level, layer); } void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer) { SafeDelete(mDepthbuffer); - mDepthbuffer = createAttachment(type, depthbuffer, level, layer); + mDepthbuffer = createAttachment(GL_DEPTH_ATTACHMENT, type, depthbuffer, level, layer); } void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer) { SafeDelete(mStencilbuffer); - mStencilbuffer = createAttachment(type, stencilbuffer, level, layer); + mStencilbuffer = createAttachment(GL_STENCIL_ATTACHMENT, type, stencilbuffer, level, layer); } void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer) { - FramebufferAttachment *attachment = createAttachment(type, depthStencilBuffer, level, layer); + FramebufferAttachment *attachment = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer); SafeDelete(mDepthbuffer); SafeDelete(mStencilbuffer); @@ -164,7 +205,7 @@ void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, // Make a new attachment object to ensure we do not double-delete // See angle issue 686 - mStencilbuffer = createAttachment(type, depthStencilBuffer, level, layer); + mStencilbuffer = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer); } } @@ -364,6 +405,7 @@ GLenum Framebuffer::completeness() const GLenum internalformat = colorbuffer->getInternalFormat(); // TODO(geofflang): use context's texture caps const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (colorbuffer->isTexture()) { if (!formatCaps.renderable) @@ -371,14 +413,14 @@ GLenum Framebuffer::completeness() const return GL_FRAMEBUFFER_UNSUPPORTED; } - if (gl::GetDepthBits(internalformat) > 0 || gl::GetStencilBits(internalformat) > 0) + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else { - if (!formatCaps.renderable || gl::GetDepthBits(internalformat) > 0 || gl::GetStencilBits(internalformat) > 0) + if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } @@ -403,7 +445,7 @@ GLenum Framebuffer::completeness() const // in GLES 3.0, there is no such restriction if (clientVersion < 3) { - if (gl::GetPixelBytes(colorbuffer->getInternalFormat()) != colorbufferSize) + if (formatInfo.pixelBytes != colorbufferSize) { return GL_FRAMEBUFFER_UNSUPPORTED; } @@ -427,7 +469,7 @@ GLenum Framebuffer::completeness() const width = colorbuffer->getWidth(); height = colorbuffer->getHeight(); samples = colorbuffer->getSamples(); - colorbufferSize = gl::GetPixelBytes(colorbuffer->getInternalFormat()); + colorbufferSize = formatInfo.pixelBytes; missingAttachment = false; } } @@ -443,10 +485,9 @@ GLenum Framebuffer::completeness() const GLenum internalformat = mDepthbuffer->getInternalFormat(); // TODO(geofflang): use context's texture caps const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (mDepthbuffer->isTexture()) { - GLenum internalformat = mDepthbuffer->getInternalFormat(); - // depth texture attachments require OES/ANGLE_depth_texture // TODO(geofflang): use context's extensions if (!mRenderer->getRendererExtensions().depthTextures) @@ -459,14 +500,14 @@ GLenum Framebuffer::completeness() const return GL_FRAMEBUFFER_UNSUPPORTED; } - if (gl::GetDepthBits(internalformat) == 0) + if (formatInfo.depthBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else { - if (!formatCaps.renderable || gl::GetDepthBits(internalformat) == 0) + if (!formatCaps.renderable || formatInfo.depthBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } @@ -499,10 +540,9 @@ GLenum Framebuffer::completeness() const GLenum internalformat = mStencilbuffer->getInternalFormat(); // TODO(geofflang): use context's texture caps const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); if (mStencilbuffer->isTexture()) { - GLenum internalformat = mStencilbuffer->getInternalFormat(); - // texture stencil attachments come along as part // of OES_packed_depth_stencil + OES/ANGLE_depth_texture // TODO(geofflang): use context's extensions @@ -516,14 +556,14 @@ GLenum Framebuffer::completeness() const return GL_FRAMEBUFFER_UNSUPPORTED; } - if (gl::GetStencilBits(internalformat) == 0) + if (formatInfo.stencilBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else { - if (!formatCaps.renderable || gl::GetStencilBits(internalformat) == 0) + if (!formatCaps.renderable || formatInfo.stencilBits == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } @@ -562,18 +602,47 @@ GLenum Framebuffer::completeness() const return GL_FRAMEBUFFER_COMPLETE; } +void Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments) +{ + GLuint maxDimension = caps.maxRenderbufferSize; + invalidateSub(caps, numAttachments, attachments, 0, 0, maxDimension, maxDimension); +} + +void Framebuffer::invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments, + GLint x, GLint y, GLsizei width, GLsizei height) +{ + ASSERT(completeness() == GL_FRAMEBUFFER_COMPLETE); + for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex) + { + GLenum attachmentTarget = attachments[attachIndex]; + + gl::FramebufferAttachment *attachment = + (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer() : + getAttachment(attachmentTarget); + + if (attachment) + { + rx::RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment); + if (renderTarget) + { + renderTarget->invalidate(x, y, width, height); + } + } + } +} + DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) : Framebuffer(renderer, 0) { Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer); - mColorbuffers[0] = new RenderbufferAttachment(colorRenderbuffer); + mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer); Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil); // Make a new attachment objects to ensure we do not double-delete // See angle issue 686 - mDepthbuffer = (depthStencilBuffer->getDepthSize() != 0 ? new RenderbufferAttachment(depthStencilBuffer) : NULL); - mStencilbuffer = (depthStencilBuffer->getStencilSize() != 0 ? new RenderbufferAttachment(depthStencilBuffer) : NULL); + 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; @@ -606,6 +675,31 @@ bool Framebuffer::hasValidDepthStencil() const mDepthbuffer->id() == mStencilbuffer->id()); } +ColorbufferInfo Framebuffer::getColorbuffersForRender() 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); + } +#if (ANGLE_MRT_PERF_WORKAROUND == ANGLE_WORKAROUND_DISABLED) + else + { + colorbuffersForRender.push_back(NULL); + } +#endif + } + + return colorbuffersForRender; +} + GLenum DefaultFramebuffer::completeness() const { // The default framebuffer *must* always be complete, though it may not be @@ -617,6 +711,7 @@ FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) cons { switch (attachment) { + case GL_COLOR: case GL_BACK: return getColorbuffer(0); case GL_DEPTH: diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h index 035e16fa45..cc12d22953 100644 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h @@ -10,6 +10,8 @@ #ifndef LIBGLESV2_FRAMEBUFFER_H_ #define LIBGLESV2_FRAMEBUFFER_H_ +#include + #include "common/angleutils.h" #include "common/RefCountObject.h" #include "constants.h" @@ -26,6 +28,9 @@ class Colorbuffer; class Depthbuffer; class Stencilbuffer; class DepthStencilbuffer; +struct Caps; + +typedef std::vector ColorbufferInfo; class Framebuffer { @@ -67,6 +72,15 @@ class Framebuffer virtual GLenum completeness() const; bool hasValidDepthStencil() const; + void invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments); + void invalidateSub(const Caps &caps, 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; + protected: rx::Renderer *mRenderer; @@ -79,10 +93,10 @@ class Framebuffer FramebufferAttachment *mDepthbuffer; FramebufferAttachment *mStencilbuffer; -private: + private: DISALLOW_COPY_AND_ASSIGN(Framebuffer); - FramebufferAttachment *createAttachment(GLenum type, GLuint handle, GLint level, GLint layer) const; + FramebufferAttachment *createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const; }; class DefaultFramebuffer : public Framebuffer @@ -99,4 +113,14 @@ class DefaultFramebuffer : public Framebuffer } +namespace rx +{ +class RenderTarget; + +// TODO: place this in FramebufferD3D.h +RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment); +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 index 5855301c97..540ede1cd2 100644 --- a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp +++ b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp @@ -1,4 +1,3 @@ -#include "precompiled.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 @@ -9,21 +8,22 @@ // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. #include "libGLESv2/FramebufferAttachment.h" -#include "libGLESv2/renderer/RenderTarget.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" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/Renderbuffer.h" namespace gl { ////// FramebufferAttachment Implementation ////// -FramebufferAttachment::FramebufferAttachment() +FramebufferAttachment::FramebufferAttachment(GLenum binding) + : mBinding(binding) { } @@ -33,42 +33,42 @@ FramebufferAttachment::~FramebufferAttachment() GLuint FramebufferAttachment::getRedSize() const { - return (gl::GetRedBits(getInternalFormat()) > 0) ? gl::GetRedBits(getActualFormat()) : 0; + return (GetInternalFormatInfo(getInternalFormat()).redBits > 0) ? GetInternalFormatInfo(getActualFormat()).redBits : 0; } GLuint FramebufferAttachment::getGreenSize() const { - return (gl::GetGreenBits(getInternalFormat()) > 0) ? gl::GetGreenBits(getActualFormat()) : 0; + return (GetInternalFormatInfo(getInternalFormat()).greenBits > 0) ? GetInternalFormatInfo(getActualFormat()).greenBits : 0; } GLuint FramebufferAttachment::getBlueSize() const { - return (gl::GetBlueBits(getInternalFormat()) > 0) ? gl::GetBlueBits(getActualFormat()) : 0; + return (GetInternalFormatInfo(getInternalFormat()).blueBits > 0) ? GetInternalFormatInfo(getActualFormat()).blueBits : 0; } GLuint FramebufferAttachment::getAlphaSize() const { - return (gl::GetAlphaBits(getInternalFormat()) > 0) ? gl::GetAlphaBits(getActualFormat()) : 0; + return (GetInternalFormatInfo(getInternalFormat()).alphaBits > 0) ? GetInternalFormatInfo(getActualFormat()).alphaBits : 0; } GLuint FramebufferAttachment::getDepthSize() const { - return (gl::GetDepthBits(getInternalFormat()) > 0) ? gl::GetDepthBits(getActualFormat()) : 0; + return (GetInternalFormatInfo(getInternalFormat()).depthBits > 0) ? GetInternalFormatInfo(getActualFormat()).depthBits : 0; } GLuint FramebufferAttachment::getStencilSize() const { - return (gl::GetStencilBits(getInternalFormat()) > 0) ? gl::GetStencilBits(getActualFormat()) : 0; + return (GetInternalFormatInfo(getInternalFormat()).stencilBits > 0) ? GetInternalFormatInfo(getActualFormat()).stencilBits : 0; } GLenum FramebufferAttachment::getComponentType() const { - return gl::GetComponentType(getActualFormat()); + return GetInternalFormatInfo(getActualFormat()).componentType; } GLenum FramebufferAttachment::getColorEncoding() const { - return gl::GetColorEncoding(getActualFormat()); + return GetInternalFormatInfo(getActualFormat()).colorEncoding; } bool FramebufferAttachment::isTexture() const @@ -76,340 +76,85 @@ bool FramebufferAttachment::isTexture() const return (type() != GL_RENDERBUFFER); } -///// Texture2DAttachment Implementation //////// - -Texture2DAttachment::Texture2DAttachment(Texture2D *texture, GLint level) : mLevel(level) -{ - mTexture2D.set(texture); -} - -Texture2DAttachment::~Texture2DAttachment() -{ - mTexture2D.set(NULL); -} - -rx::RenderTarget *Texture2DAttachment::getRenderTarget() -{ - return mTexture2D->getRenderTarget(mLevel); -} - -rx::RenderTarget *Texture2DAttachment::getDepthStencil() -{ - return mTexture2D->getDepthSencil(mLevel); -} - -rx::TextureStorage *Texture2DAttachment::getTextureStorage() -{ - return mTexture2D->getNativeTexture()->getStorageInstance(); -} - -GLsizei Texture2DAttachment::getWidth() const -{ - return mTexture2D->getWidth(mLevel); -} - -GLsizei Texture2DAttachment::getHeight() const -{ - return mTexture2D->getHeight(mLevel); -} - -GLenum Texture2DAttachment::getInternalFormat() const -{ - return mTexture2D->getInternalFormat(mLevel); -} - -GLenum Texture2DAttachment::getActualFormat() const -{ - return mTexture2D->getActualFormat(mLevel); -} - -GLsizei Texture2DAttachment::getSamples() const -{ - return 0; -} - -unsigned int Texture2DAttachment::getSerial() const -{ - return mTexture2D->getRenderTargetSerial(mLevel); -} - -GLuint Texture2DAttachment::id() const -{ - return mTexture2D->id(); -} - -GLenum Texture2DAttachment::type() const -{ - return GL_TEXTURE_2D; -} - -GLint Texture2DAttachment::mipLevel() const -{ - return mLevel; -} - -GLint Texture2DAttachment::layer() const -{ - return 0; -} - -unsigned int Texture2DAttachment::getTextureSerial() const -{ - return mTexture2D->getTextureSerial(); -} - -///// TextureCubeMapAttachment Implementation //////// - -TextureCubeMapAttachment::TextureCubeMapAttachment(TextureCubeMap *texture, GLenum faceTarget, GLint level) - : mFaceTarget(faceTarget), mLevel(level) -{ - mTextureCubeMap.set(texture); -} - -TextureCubeMapAttachment::~TextureCubeMapAttachment() -{ - mTextureCubeMap.set(NULL); -} - -rx::RenderTarget *TextureCubeMapAttachment::getRenderTarget() -{ - return mTextureCubeMap->getRenderTarget(mFaceTarget, mLevel); -} - -rx::RenderTarget *TextureCubeMapAttachment::getDepthStencil() -{ - return mTextureCubeMap->getDepthStencil(mFaceTarget, mLevel); -} - -rx::TextureStorage *TextureCubeMapAttachment::getTextureStorage() -{ - return mTextureCubeMap->getNativeTexture()->getStorageInstance(); -} - -GLsizei TextureCubeMapAttachment::getWidth() const -{ - return mTextureCubeMap->getWidth(mFaceTarget, mLevel); -} - -GLsizei TextureCubeMapAttachment::getHeight() const -{ - return mTextureCubeMap->getHeight(mFaceTarget, mLevel); -} - -GLenum TextureCubeMapAttachment::getInternalFormat() const -{ - return mTextureCubeMap->getInternalFormat(mFaceTarget, mLevel); -} - -GLenum TextureCubeMapAttachment::getActualFormat() const -{ - return mTextureCubeMap->getActualFormat(mFaceTarget, mLevel); -} - -GLsizei TextureCubeMapAttachment::getSamples() const -{ - return 0; -} - -unsigned int TextureCubeMapAttachment::getSerial() const -{ - return mTextureCubeMap->getRenderTargetSerial(mFaceTarget, mLevel); -} - -GLuint TextureCubeMapAttachment::id() const -{ - return mTextureCubeMap->id(); -} - -GLenum TextureCubeMapAttachment::type() const -{ - return mFaceTarget; -} - -GLint TextureCubeMapAttachment::mipLevel() const -{ - return mLevel; -} - -GLint TextureCubeMapAttachment::layer() const -{ - return 0; -} - -unsigned int TextureCubeMapAttachment::getTextureSerial() const -{ - return mTextureCubeMap->getTextureSerial(); -} - -///// Texture3DAttachment Implementation //////// - -Texture3DAttachment::Texture3DAttachment(Texture3D *texture, GLint level, GLint layer) - : mLevel(level), mLayer(layer) -{ - mTexture3D.set(texture); -} - -Texture3DAttachment::~Texture3DAttachment() -{ - mTexture3D.set(NULL); -} - -rx::RenderTarget *Texture3DAttachment::getRenderTarget() -{ - return mTexture3D->getRenderTarget(mLevel, mLayer); -} - -rx::RenderTarget *Texture3DAttachment::getDepthStencil() -{ - return mTexture3D->getDepthStencil(mLevel, mLayer); -} - -rx::TextureStorage *Texture3DAttachment::getTextureStorage() -{ - return mTexture3D->getNativeTexture()->getStorageInstance(); -} - -GLsizei Texture3DAttachment::getWidth() const -{ - return mTexture3D->getWidth(mLevel); -} - -GLsizei Texture3DAttachment::getHeight() const -{ - return mTexture3D->getHeight(mLevel); -} +///// TextureAttachment Implementation //////// -GLenum Texture3DAttachment::getInternalFormat() const +TextureAttachment::TextureAttachment(GLenum binding, Texture *texture, const ImageIndex &index) + : FramebufferAttachment(binding), + mIndex(index) { - return mTexture3D->getInternalFormat(mLevel); + mTexture.set(texture); } -GLenum Texture3DAttachment::getActualFormat() const +TextureAttachment::~TextureAttachment() { - return mTexture3D->getActualFormat(mLevel); + mTexture.set(NULL); } -GLsizei Texture3DAttachment::getSamples() const +GLsizei TextureAttachment::getSamples() const { return 0; } -unsigned int Texture3DAttachment::getSerial() const -{ - return mTexture3D->getRenderTargetSerial(mLevel, mLayer); -} - -GLuint Texture3DAttachment::id() const -{ - return mTexture3D->id(); -} - -GLenum Texture3DAttachment::type() const -{ - return GL_TEXTURE_3D; -} - -GLint Texture3DAttachment::mipLevel() const -{ - return mLevel; -} - -GLint Texture3DAttachment::layer() const -{ - return mLayer; -} - -unsigned int Texture3DAttachment::getTextureSerial() const -{ - return mTexture3D->getTextureSerial(); -} - -////// Texture2DArrayAttachment Implementation ////// - -Texture2DArrayAttachment::Texture2DArrayAttachment(Texture2DArray *texture, GLint level, GLint layer) - : mLevel(level), mLayer(layer) -{ - mTexture2DArray.set(texture); -} - -Texture2DArrayAttachment::~Texture2DArrayAttachment() -{ - mTexture2DArray.set(NULL); -} - -rx::RenderTarget *Texture2DArrayAttachment::getRenderTarget() +GLuint TextureAttachment::id() const { - return mTexture2DArray->getRenderTarget(mLevel, mLayer); + return mTexture->id(); } -rx::RenderTarget *Texture2DArrayAttachment::getDepthStencil() +GLsizei TextureAttachment::getWidth() const { - return mTexture2DArray->getDepthStencil(mLevel, mLayer); + return mTexture->getWidth(mIndex); } -rx::TextureStorage *Texture2DArrayAttachment::getTextureStorage() +GLsizei TextureAttachment::getHeight() const { - return mTexture2DArray->getNativeTexture()->getStorageInstance(); + return mTexture->getHeight(mIndex); } -GLsizei Texture2DArrayAttachment::getWidth() const +GLenum TextureAttachment::getInternalFormat() const { - return mTexture2DArray->getWidth(mLevel); + return mTexture->getInternalFormat(mIndex); } -GLsizei Texture2DArrayAttachment::getHeight() const +GLenum TextureAttachment::getActualFormat() const { - return mTexture2DArray->getHeight(mLevel); + return mTexture->getActualFormat(mIndex); } -GLenum Texture2DArrayAttachment::getInternalFormat() const +GLenum TextureAttachment::type() const { - return mTexture2DArray->getInternalFormat(mLevel); + return mIndex.type; } -GLenum Texture2DArrayAttachment::getActualFormat() const +GLint TextureAttachment::mipLevel() const { - return mTexture2DArray->getActualFormat(mLevel); + return mIndex.mipIndex; } -GLsizei Texture2DArrayAttachment::getSamples() const +GLint TextureAttachment::layer() const { - return 0; -} - -unsigned int Texture2DArrayAttachment::getSerial() const -{ - return mTexture2DArray->getRenderTargetSerial(mLevel, mLayer); -} - -GLuint Texture2DArrayAttachment::id() const -{ - return mTexture2DArray->id(); -} - -GLenum Texture2DArrayAttachment::type() const -{ - return GL_TEXTURE_2D_ARRAY; + return mIndex.layerIndex; } -GLint Texture2DArrayAttachment::mipLevel() const +Texture *TextureAttachment::getTexture() { - return mLevel; + return mTexture.get(); } -GLint Texture2DArrayAttachment::layer() const +const ImageIndex *TextureAttachment::getTextureImageIndex() const { - return mLayer; + return &mIndex; } -unsigned int Texture2DArrayAttachment::getTextureSerial() const +Renderbuffer *TextureAttachment::getRenderbuffer() { - return mTexture2DArray->getTextureSerial(); + UNREACHABLE(); + return NULL; } ////// RenderbufferAttachment Implementation ////// -RenderbufferAttachment::RenderbufferAttachment(Renderbuffer *renderbuffer) +RenderbufferAttachment::RenderbufferAttachment(GLenum binding, Renderbuffer *renderbuffer) + : FramebufferAttachment(binding) { ASSERT(renderbuffer); mRenderbuffer.set(renderbuffer); @@ -420,22 +165,6 @@ RenderbufferAttachment::~RenderbufferAttachment() mRenderbuffer.set(NULL); } -rx::RenderTarget *RenderbufferAttachment::getRenderTarget() -{ - return mRenderbuffer->getStorage()->getRenderTarget(); -} - -rx::RenderTarget *RenderbufferAttachment::getDepthStencil() -{ - return mRenderbuffer->getStorage()->getDepthStencil(); -} - -rx::TextureStorage *RenderbufferAttachment::getTextureStorage() -{ - UNREACHABLE(); - return NULL; -} - GLsizei RenderbufferAttachment::getWidth() const { return mRenderbuffer->getWidth(); @@ -461,11 +190,6 @@ GLsizei RenderbufferAttachment::getSamples() const return mRenderbuffer->getStorage()->getSamples(); } -unsigned int RenderbufferAttachment::getSerial() const -{ - return mRenderbuffer->getStorage()->getSerial(); -} - GLuint RenderbufferAttachment::id() const { return mRenderbuffer->id(); @@ -486,10 +210,21 @@ GLint RenderbufferAttachment::layer() const return 0; } -unsigned int RenderbufferAttachment::getTextureSerial() const +Texture *RenderbufferAttachment::getTexture() { UNREACHABLE(); - return 0; + 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 index 18768f9831..c18ef7364d 100644 --- a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h +++ b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h @@ -10,10 +10,11 @@ #ifndef LIBGLESV2_FRAMEBUFFERATTACHMENT_H_ #define LIBGLESV2_FRAMEBUFFERATTACHMENT_H_ -#include "angle_gl.h" - #include "common/angleutils.h" #include "common/RefCountObject.h" +#include "Texture.h" + +#include "angle_gl.h" namespace rx { @@ -24,10 +25,6 @@ class TextureStorage; namespace gl { -class Texture2D; -class TextureCubeMap; -class Texture3D; -class Texture2DArray; class Renderbuffer; // FramebufferAttachment implements a GL framebuffer attachment. @@ -39,7 +36,7 @@ class Renderbuffer; class FramebufferAttachment { public: - FramebufferAttachment(); + explicit FramebufferAttachment(GLenum binding); virtual ~FramebufferAttachment(); // Helper methods @@ -56,184 +53,80 @@ class FramebufferAttachment bool isTextureWithId(GLuint textureId) const { return isTexture() && id() == textureId; } bool isRenderbufferWithId(GLuint renderbufferId) const { return !isTexture() && id() == renderbufferId; } - // Child class interface - virtual rx::RenderTarget *getRenderTarget() = 0; - virtual rx::RenderTarget *getDepthStencil() = 0; - virtual rx::TextureStorage *getTextureStorage() = 0; + 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 unsigned int getSerial() const = 0; - virtual GLuint id() const = 0; virtual GLenum type() const = 0; virtual GLint mipLevel() const = 0; virtual GLint layer() const = 0; - virtual unsigned int getTextureSerial() const = 0; - private: - DISALLOW_COPY_AND_ASSIGN(FramebufferAttachment); -}; - -class Texture2DAttachment : public FramebufferAttachment -{ - public: - Texture2DAttachment(Texture2D *texture, GLint level); - - virtual ~Texture2DAttachment(); - - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - rx::TextureStorage *getTextureStorage(); - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; - virtual GLsizei getSamples() const; - - virtual unsigned int getSerial() const; - - virtual GLuint id() const; - virtual GLenum type() const; - virtual GLint mipLevel() const; - virtual GLint layer() const; - virtual unsigned int getTextureSerial() const; + virtual Texture *getTexture() = 0; + virtual const ImageIndex *getTextureImageIndex() const = 0; + virtual Renderbuffer *getRenderbuffer() = 0; private: - DISALLOW_COPY_AND_ASSIGN(Texture2DAttachment); + DISALLOW_COPY_AND_ASSIGN(FramebufferAttachment); - BindingPointer mTexture2D; - const GLint mLevel; + GLenum mBinding; }; -class TextureCubeMapAttachment : public FramebufferAttachment +class TextureAttachment : public FramebufferAttachment { public: - TextureCubeMapAttachment(TextureCubeMap *texture, GLenum faceTarget, GLint level); + TextureAttachment(GLenum binding, Texture *texture, const ImageIndex &index); + virtual ~TextureAttachment(); - virtual ~TextureCubeMapAttachment(); - - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - rx::TextureStorage *getTextureStorage(); - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; virtual GLsizei getSamples() const; - - virtual unsigned int getSerial() const; - virtual GLuint id() const; - virtual GLenum type() const; - virtual GLint mipLevel() const; - virtual GLint layer() const; - virtual unsigned int getTextureSerial() const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureCubeMapAttachment); - - BindingPointer mTextureCubeMap; - const GLint mLevel; - const GLenum mFaceTarget; -}; - -class Texture3DAttachment : public FramebufferAttachment -{ - public: - Texture3DAttachment(Texture3D *texture, GLint level, GLint layer); - - virtual ~Texture3DAttachment(); - - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - rx::TextureStorage *getTextureStorage(); virtual GLsizei getWidth() const; virtual GLsizei getHeight() const; virtual GLenum getInternalFormat() const; virtual GLenum getActualFormat() const; - virtual GLsizei getSamples() const; - - virtual unsigned int getSerial() const; - virtual GLuint id() const; virtual GLenum type() const; virtual GLint mipLevel() const; virtual GLint layer() const; - virtual unsigned int getTextureSerial() const; - private: - DISALLOW_COPY_AND_ASSIGN(Texture3DAttachment); - - BindingPointer mTexture3D; - const GLint mLevel; - const GLint mLayer; -}; - -class Texture2DArrayAttachment : public FramebufferAttachment -{ - public: - Texture2DArrayAttachment(Texture2DArray *texture, GLint level, GLint layer); - - virtual ~Texture2DArrayAttachment(); - - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - rx::TextureStorage *getTextureStorage(); - - virtual GLsizei getWidth() const; - virtual GLsizei getHeight() const; - virtual GLenum getInternalFormat() const; - virtual GLenum getActualFormat() const; - virtual GLsizei getSamples() const; - - virtual unsigned int getSerial() const; - - virtual GLuint id() const; - virtual GLenum type() const; - virtual GLint mipLevel() const; - virtual GLint layer() const; - virtual unsigned int getTextureSerial() const; + virtual Texture *getTexture(); + virtual const ImageIndex *getTextureImageIndex() const; + virtual Renderbuffer *getRenderbuffer(); private: - DISALLOW_COPY_AND_ASSIGN(Texture2DArrayAttachment); + DISALLOW_COPY_AND_ASSIGN(TextureAttachment); - BindingPointer mTexture2DArray; - const GLint mLevel; - const GLint mLayer; + BindingPointer mTexture; + ImageIndex mIndex; }; class RenderbufferAttachment : public FramebufferAttachment { public: - RenderbufferAttachment(Renderbuffer *renderbuffer); + RenderbufferAttachment(GLenum binding, Renderbuffer *renderbuffer); virtual ~RenderbufferAttachment(); - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - rx::TextureStorage *getTextureStorage(); - virtual GLsizei getWidth() const; virtual GLsizei getHeight() const; virtual GLenum getInternalFormat() const; virtual GLenum getActualFormat() const; virtual GLsizei getSamples() const; - virtual unsigned int getSerial() const; - virtual GLuint id() const; virtual GLenum type() const; virtual GLint mipLevel() const; virtual GLint layer() const; - virtual unsigned int getTextureSerial() const; + + virtual Texture *getTexture(); + virtual const ImageIndex *getTextureImageIndex() const; + virtual Renderbuffer *getRenderbuffer(); private: DISALLOW_COPY_AND_ASSIGN(RenderbufferAttachment); diff --git a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp index 37da99aa18..c498f8a178 100644 --- a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp +++ b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be diff --git a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h index bbded02f99..a89cc86775 100644 --- a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h +++ b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h @@ -10,12 +10,12 @@ #ifndef LIBGLESV2_HANDLEALLOCATOR_H_ #define LIBGLESV2_HANDLEALLOCATOR_H_ +#include "common/angleutils.h" + #include "angle_gl.h" #include -#include "common/angleutils.h" - namespace gl { diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp b/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp new file mode 100644 index 0000000000..3522b997e8 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp @@ -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. +// + +// 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(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn) + : type(typeIn), + mipIndex(mipIndexIn), + layerIndex(layerIndexIn) +{} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.h b/src/3rdparty/angle/src/libGLESv2/ImageIndex.h new file mode 100644 index 0000000000..9f2df88061 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/ImageIndex.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. +// + +// 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" + +namespace gl +{ + +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 const GLint ENTIRE_LEVEL = static_cast(-1); + + private: + ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn); +}; + +} + +#endif // LIBGLESV2_IMAGE_INDEX_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Program.cpp b/src/3rdparty/angle/src/libGLESv2/Program.cpp index 8a9fb04800..9bfda09a64 100644 --- a/src/3rdparty/angle/src/libGLESv2/Program.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Program.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -11,6 +10,7 @@ #include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/ResourceManager.h" +#include "libGLESv2/renderer/Renderer.h" namespace gl { @@ -173,7 +173,7 @@ bool Program::attachShader(Shader *shader) return false; } - mVertexShader = (VertexShader*)shader; + mVertexShader = shader; mVertexShader->addRef(); } else if (shader->getType() == GL_FRAGMENT_SHADER) @@ -183,7 +183,7 @@ bool Program::attachShader(Shader *shader) return false; } - mFragmentShader = (FragmentShader*)shader; + mFragmentShader = shader; mFragmentShader->addRef(); } else UNREACHABLE(); @@ -244,16 +244,16 @@ void Program::bindAttributeLocation(GLuint index, const char *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 -bool Program::link() +bool Program::link(const Caps &caps) { unlink(false); mInfoLog.reset(); resetUniformBlockBindings(); - mProgramBinary.set(new ProgramBinary(mRenderer)); + mProgramBinary.set(new ProgramBinary(mRenderer->createProgram())); mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader, - mTransformFeedbackVaryings, mTransformFeedbackBufferMode); + mTransformFeedbackVaryings, mTransformFeedbackBufferMode, caps); return mLinked; } @@ -303,14 +303,15 @@ ProgramBinary* Program::getProgramBinary() const return mProgramBinary.get(); } -bool Program::setProgramBinary(const void *binary, GLsizei length) +bool Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length) { unlink(false); mInfoLog.reset(); - mProgramBinary.set(new ProgramBinary(mRenderer)); - mLinked = mProgramBinary->load(mInfoLog, binary, length); + mProgramBinary.set(new ProgramBinary(mRenderer->createProgram())); + mLinked = mProgramBinary->load(mInfoLog, binaryFormat, binary, length); + if (!mLinked) { mProgramBinary.set(NULL); @@ -502,14 +503,14 @@ bool Program::isFlaggedForDeletion() const return mDeleteStatus; } -void Program::validate() +void Program::validate(const Caps &caps) { mInfoLog.reset(); ProgramBinary *programBinary = getProgramBinary(); if (isLinked() && programBinary) { - programBinary->validate(mInfoLog); + programBinary->validate(mInfoLog, caps); } else { diff --git a/src/3rdparty/angle/src/libGLESv2/Program.h b/src/3rdparty/angle/src/libGLESv2/Program.h index ce821a470b..6528dd1191 100644 --- a/src/3rdparty/angle/src/libGLESv2/Program.h +++ b/src/3rdparty/angle/src/libGLESv2/Program.h @@ -10,14 +10,17 @@ #ifndef LIBGLESV2_PROGRAM_H_ #define LIBGLESV2_PROGRAM_H_ -#include -#include - #include "common/angleutils.h" #include "common/RefCountObject.h" #include "libGLESv2/Constants.h" #include "libGLESv2/ProgramBinary.h" +#include + +#include +#include +#include + namespace rx { class Renderer; @@ -25,9 +28,8 @@ class Renderer; namespace gl { +struct Caps; class ResourceManager; -class FragmentShader; -class VertexShader; class Shader; extern const char * const g_fakepath; @@ -75,9 +77,9 @@ class Program void bindAttributeLocation(GLuint index, const char *name); - bool link(); + bool link(const Caps &caps); bool isLinked(); - bool setProgramBinary(const void *binary, GLsizei length); + bool setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length); ProgramBinary *getProgramBinary() const; int getInfoLogLength() const; @@ -110,7 +112,7 @@ class Program void flagForDeletion(); bool isFlaggedForDeletion() const; - void validate(); + void validate(const Caps &caps); bool isValidated() const; GLint getProgramBinaryLength() const; @@ -121,8 +123,8 @@ class Program void unlink(bool destroy = false); void resetUniformBlockBindings(); - FragmentShader *mFragmentShader; - VertexShader *mVertexShader; + Shader *mFragmentShader; + Shader *mVertexShader; AttributeBindings mAttributeBindings; diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp index 9fad5fbfc5..3f6d9e0ef9 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -11,33 +10,34 @@ #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/Renderer.h" +#include "libGLESv2/renderer/d3d/DynamicHLSL.h" +#include "libGLESv2/renderer/d3d/ShaderD3D.h" #include "libGLESv2/renderer/d3d/VertexDataManager.h" #include "libGLESv2/Context.h" #include "libGLESv2/Buffer.h" -#include "libGLESv2/DynamicHLSL.h" #include "common/blocklayout.h" -#undef near -#undef far - namespace gl { namespace { -TextureType GetTextureType(GLenum samplerType) +GLenum GetTextureType(GLenum samplerType) { switch (samplerType) { @@ -45,26 +45,26 @@ TextureType GetTextureType(GLenum samplerType) case GL_INT_SAMPLER_2D: case GL_UNSIGNED_INT_SAMPLER_2D: case GL_SAMPLER_2D_SHADOW: - return TEXTURE_2D; + return GL_TEXTURE_2D; case GL_SAMPLER_3D: case GL_INT_SAMPLER_3D: case GL_UNSIGNED_INT_SAMPLER_3D: - return TEXTURE_3D; + return GL_TEXTURE_3D; case GL_SAMPLER_CUBE: case GL_SAMPLER_CUBE_SHADOW: - return TEXTURE_CUBE; + return GL_TEXTURE_CUBE_MAP; case GL_INT_SAMPLER_CUBE: case GL_UNSIGNED_INT_SAMPLER_CUBE: - return TEXTURE_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 TEXTURE_2D_ARRAY; + return GL_TEXTURE_2D_ARRAY; default: UNREACHABLE(); } - return TEXTURE_2D; + return GL_TEXTURE_2D; } unsigned int ParseAndStripArrayIndex(std::string* name) @@ -83,7 +83,7 @@ unsigned int ParseAndStripArrayIndex(std::string* name) return subscript; } -void GetInputLayoutFromShader(const std::vector &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) +void GetDefaultInputLayoutFromShader(const std::vector &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) { size_t layoutIndex = 0; for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) @@ -109,6 +109,26 @@ void GetInputLayoutFromShader(const std::vector &shaderAttributes } } +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; +} + } VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index) @@ -169,45 +189,30 @@ LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, unsigned int ProgramBinary::mCurrentSerial = 1; -ProgramBinary::ProgramBinary(rx::Renderer *renderer) +ProgramBinary::ProgramBinary(rx::ProgramImpl *impl) : RefCountObject(0), - mRenderer(renderer), - mDynamicHLSL(NULL), - mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE), - mPixelWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE), + mProgram(impl), mGeometryExecutable(NULL), mUsedVertexSamplerRange(0), mUsedPixelSamplerRange(0), mUsesPointSize(false), mShaderVersion(100), mDirtySamplerMapping(true), - mVertexUniformStorage(NULL), - mFragmentUniformStorage(NULL), mValidated(false), mSerial(issueSerial()) { + ASSERT(impl); + for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++) { mSemanticIndex[index] = -1; } - - for (int index = 0; index < MAX_TEXTURE_IMAGE_UNITS; index++) - { - mSamplersPS[index].active = false; - } - - for (int index = 0; index < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; index++) - { - mSamplersVS[index].active = false; - } - - mDynamicHLSL = new DynamicHLSL(renderer); } ProgramBinary::~ProgramBinary() { reset(); - SafeDelete(mDynamicHLSL); + SafeDelete(mProgram); } unsigned int ProgramBinary::getSerial() const @@ -227,17 +232,21 @@ unsigned int ProgramBinary::issueSerial() rx::ShaderExecutable *ProgramBinary::getPixelExecutableForFramebuffer(const Framebuffer *fbo) { - std::vector outputs(IMPLEMENTATION_MAX_DRAW_BUFFERS); - for (size_t outputIndex = 0; outputIndex < IMPLEMENTATION_MAX_DRAW_BUFFERS; outputIndex++) + std::vector outputs; + + const gl::ColorbufferInfo &colorbuffers = fbo->getColorbuffersForRender(); + + for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) { - if (fbo->getColorbuffer(outputIndex) != NULL) + const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; + + if (colorbuffer) { - // Always output floats for now - outputs[outputIndex] = GL_FLOAT; + outputs.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding()); } else { - outputs[outputIndex] = GL_NONE; + outputs.push_back(GL_NONE); } } @@ -254,15 +263,9 @@ rx::ShaderExecutable *ProgramBinary::getPixelExecutableForOutputLayout(const std } } - std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth, - outputSignature); - - // Generate new pixel executable InfoLog tempInfoLog; - rx::ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL.c_str(), rx::SHADER_PIXEL, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - mPixelWorkarounds); + rx::ShaderExecutable *pixelExecutable = mProgram->getPixelExecutableForOutputLayout(tempInfoLog, outputSignature, + mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); if (!pixelExecutable) { @@ -281,7 +284,7 @@ rx::ShaderExecutable *ProgramBinary::getPixelExecutableForOutputLayout(const std rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) { GLenum signature[MAX_VERTEX_ATTRIBS]; - mDynamicHLSL->getInputLayoutSignature(inputLayout, signature); + mProgram->getDynamicHLSL()->getInputLayoutSignature(inputLayout, signature); for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++) { @@ -291,16 +294,9 @@ rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const Ver } } - // Generate new dynamic layout with attribute conversions - std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes); - - // Generate new vertex executable InfoLog tempInfoLog; - rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL.c_str(), - rx::SHADER_VERTEX, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - mVertexWorkarounds); + rx::ShaderExecutable *vertexExecutable = mProgram->getVertexExecutableForInputLayout(tempInfoLog, inputLayout, mShaderAttributes, + mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); if (!vertexExecutable) { @@ -366,7 +362,7 @@ bool ProgramBinary::usesPointSize() const bool ProgramBinary::usesPointSpriteEmulation() const { - return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4; + return mUsesPointSize && mProgram->getRenderer()->getMajorShaderModel() >= 4; } bool ProgramBinary::usesGeometryShader() const @@ -374,26 +370,22 @@ bool ProgramBinary::usesGeometryShader() const return usesPointSpriteEmulation(); } -// Returns the index of the texture image unit (0-19) corresponding to a Direct3D 9 sampler -// index (0-15 for the pixel shader and 0-3 for the vertex shader). -GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex) +GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps) { GLint logicalTextureUnit = -1; switch (type) { case SAMPLER_PIXEL: - ASSERT(samplerIndex < ArraySize(mSamplersPS)); - - if (mSamplersPS[samplerIndex].active) + ASSERT(samplerIndex < caps.maxTextureImageUnits); + if (samplerIndex < mSamplersPS.size() && mSamplersPS[samplerIndex].active) { logicalTextureUnit = mSamplersPS[samplerIndex].logicalTextureUnit; } break; case SAMPLER_VERTEX: - ASSERT(samplerIndex < ArraySize(mSamplersVS)); - - if (mSamplersVS[samplerIndex].active) + ASSERT(samplerIndex < caps.maxVertexTextureImageUnits); + if (samplerIndex < mSamplersVS.size() && mSamplersVS[samplerIndex].active) { logicalTextureUnit = mSamplersVS[samplerIndex].logicalTextureUnit; } @@ -401,7 +393,7 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd default: UNREACHABLE(); } - if (logicalTextureUnit >= 0 && logicalTextureUnit < (GLint)mRenderer->getMaxCombinedTextureImageUnits()) + if (logicalTextureUnit >= 0 && logicalTextureUnit < static_cast(caps.maxCombinedTextureImageUnits)) { return logicalTextureUnit; } @@ -411,22 +403,22 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd // Returns the texture type for a given Direct3D 9 sampler type and // index (0-15 for the pixel shader and 0-3 for the vertex shader). -TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex) +GLenum ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex) { switch (type) { case SAMPLER_PIXEL: - ASSERT(samplerIndex < ArraySize(mSamplersPS)); + ASSERT(samplerIndex < mSamplersPS.size()); ASSERT(mSamplersPS[samplerIndex].active); return mSamplersPS[samplerIndex].textureType; case SAMPLER_VERTEX: - ASSERT(samplerIndex < ArraySize(mSamplersVS)); + ASSERT(samplerIndex < mSamplersVS.size()); ASSERT(mSamplersVS[samplerIndex].active); return mSamplersVS[samplerIndex].textureType; default: UNREACHABLE(); } - return TEXTURE_2D; + return GL_TEXTURE_2D; } GLint ProgramBinary::getUniformLocation(std::string name) @@ -562,38 +554,64 @@ void ProgramBinary::setUniform(GLint location, GLsizei count, const T* v, GLenum if (targetUniform->type == targetUniformType) { - T *target = (T*)targetUniform->data + mUniformIndex[location].element * 4; + 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(target + c, v[c], &targetUniform->dirty); + SetIfDirty(dest + c, source[c], &targetUniform->dirty); } for (int c = components; c < 4; c++) { - SetIfDirty(target + c, T(0), &targetUniform->dirty); + SetIfDirty(dest + c, T(0), &targetUniform->dirty); } - target += 4; - v += components; } } else if (targetUniform->type == targetBoolType) { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; + 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(boolParams + c, (v[c] == static_cast(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty); + SetIfDirty(dest + c, (source[c] == static_cast(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty); } for (int c = components; c < 4; c++) { - SetIfDirty(boolParams + c, GL_FALSE, &targetUniform->dirty); + SetIfDirty(dest + c, GL_FALSE, &targetUniform->dirty); } - boolParams += 4; - v += components; + } + } + else if (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(); @@ -761,48 +779,7 @@ void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboole void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) { - LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index]; - - int elementCount = targetUniform->elementCount(); - - count = std::min(elementCount - (int)mUniformIndex[location].element, count); - - if (targetUniform->type == GL_INT || IsSampler(targetUniform->type)) - { - GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - SetIfDirty(target + 0, v[0], &targetUniform->dirty); - SetIfDirty(target + 1, 0, &targetUniform->dirty); - SetIfDirty(target + 2, 0, &targetUniform->dirty); - SetIfDirty(target + 3, 0, &targetUniform->dirty); - target += 4; - v += 1; - } - } - else if (targetUniform->type == GL_BOOL) - { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - SetIfDirty(boolParams + 0, (v[0] == 0) ? GL_FALSE : GL_TRUE, &targetUniform->dirty); - SetIfDirty(boolParams + 1, GL_FALSE, &targetUniform->dirty); - SetIfDirty(boolParams + 2, GL_FALSE, &targetUniform->dirty); - SetIfDirty(boolParams + 3, GL_FALSE, &targetUniform->dirty); - boolParams += 4; - v += 1; - } - } - else UNREACHABLE(); - - // Set a special flag if we change a sampler uniform - if (IsSampler(targetUniform->type) && - (memcmp(targetUniform->data, v, sizeof(GLint)) != 0)) - { - mDirtySamplerMapping = true; - } + setUniform(location, count, v, GL_INT); } void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) @@ -841,20 +818,10 @@ void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint * } template -bool ProgramBinary::getUniformv(GLint location, GLsizei *bufSize, T *params, GLenum uniformType) +void ProgramBinary::getUniformv(GLint location, T *params, GLenum uniformType) { LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index]; - // sized queries -- ensure the provided buffer is large enough - if (bufSize) - { - int requiredBytes = VariableExternalSize(targetUniform->type); - if (*bufSize < requiredBytes) - { - return false; - } - } - if (IsMatrixType(targetUniform->type)) { const int rows = VariableRowCount(targetUniform->type); @@ -919,23 +886,21 @@ bool ProgramBinary::getUniformv(GLint location, GLsizei *bufSize, T *params, GLe default: UNREACHABLE(); } } - - return true; } -bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params) +void ProgramBinary::getUniformfv(GLint location, GLfloat *params) { - return getUniformv(location, bufSize, params, GL_FLOAT); + getUniformv(location, params, GL_FLOAT); } -bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params) +void ProgramBinary::getUniformiv(GLint location, GLint *params) { - return getUniformv(location, bufSize, params, GL_INT); + getUniformv(location, params, GL_INT); } -bool ProgramBinary::getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params) +void ProgramBinary::getUniformuiv(GLint location, GLuint *params) { - return getUniformv(location, bufSize, params, GL_UNSIGNED_INT); + getUniformv(location, params, GL_UNSIGNED_INT); } void ProgramBinary::dirtyAllUniforms() @@ -976,7 +941,7 @@ void ProgramBinary::updateSamplerMapping() { unsigned int samplerIndex = firstIndex + i; - if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) + if (samplerIndex < mSamplersPS.size()) { ASSERT(mSamplersPS[samplerIndex].active); mSamplersPS[samplerIndex].logicalTextureUnit = v[i][0]; @@ -992,7 +957,7 @@ void ProgramBinary::updateSamplerMapping() { unsigned int samplerIndex = firstIndex + i; - if (samplerIndex < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS) + if (samplerIndex < mSamplersVS.size()) { ASSERT(mSamplersVS[samplerIndex].active); mSamplersVS[samplerIndex].logicalTextureUnit = v[i][0]; @@ -1005,25 +970,31 @@ void ProgramBinary::updateSamplerMapping() } // Applies all the uniforms set for this program object to the renderer -void ProgramBinary::applyUniforms() +Error ProgramBinary::applyUniforms() { updateSamplerMapping(); - mRenderer->applyUniforms(*this); + Error error = mProgram->getRenderer()->applyUniforms(*this); + if (error.isError()) + { + return error; + } for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) { mUniforms[uniformIndex]->dirty = false; } + + return gl::Error(GL_NO_ERROR); } -bool ProgramBinary::applyUniformBuffers(const std::vector boundBuffers) +Error ProgramBinary::applyUniformBuffers(const std::vector boundBuffers, const Caps &caps) { 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(); + const unsigned int reservedBuffersInVS = mProgram->getRenderer()->getReservedVertexUniformBuffers(); + const unsigned int reservedBuffersInFS = mProgram->getRenderer()->getReservedFragmentUniformBuffers(); ASSERT(boundBuffers.size() == mUniformBlocks.size()); @@ -1037,16 +1008,20 @@ bool ProgramBinary::applyUniformBuffers(const std::vector boundBuff if (uniformBuffer->getSize() < uniformBlock->dataSize) { // undefined behaviour - return false; + return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small."); } - ASSERT(uniformBlock->isReferencedByVertexShader() || uniformBlock->isReferencedByFragmentShader()); + // 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 < mRenderer->getMaxVertexShaderUniformBuffers()); + ASSERT(registerIndex < caps.maxVertexUniformBlocks); vertexUniformBuffers[registerIndex] = uniformBuffer; } @@ -1054,15 +1029,15 @@ bool ProgramBinary::applyUniformBuffers(const std::vector boundBuff { unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS; ASSERT(fragmentUniformBuffers[registerIndex] == NULL); - ASSERT(registerIndex < mRenderer->getMaxFragmentShaderUniformBuffers()); + ASSERT(registerIndex < caps.maxFragmentUniformBlocks); fragmentUniformBuffers[registerIndex] = uniformBuffer; } } - return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers); + return mProgram->getRenderer()->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers); } -bool ProgramBinary::linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader) +bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader) { std::vector &fragmentVaryings = fragmentShader->getVaryings(); std::vector &vertexVaryings = vertexShader->getVaryings(); @@ -1072,24 +1047,32 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShade 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 (!linkValidateVariables(infoLog, output->name, *input, *output)) + if (!linkValidateVaryings(infoLog, output->name, *input, *output)) { return false; } output->registerIndex = input->registerIndex; + output->columnIndex = input->columnIndex; matched = true; break; } } - if (!matched) + // 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; @@ -1099,17 +1082,19 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShade return true; } -bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) +bool ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length) { #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD return false; #else + ASSERT(binaryFormat == mProgram->getBinaryFormat()); + reset(); BinaryInputStream stream(binary, length); - int format = stream.readInt(); - if (format != GL_PROGRAM_BINARY_ANGLE) + GLenum format = stream.readInt(); + if (format != mProgram->getBinaryFormat()) { infoLog.append("Invalid program binary format."); return false; @@ -1149,18 +1134,23 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) initAttributesByLayout(); - for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) + const unsigned int psSamplerCount = stream.readInt(); + for (unsigned int i = 0; i < psSamplerCount; ++i) { - stream.readBool(&mSamplersPS[i].active); - stream.readInt(&mSamplersPS[i].logicalTextureUnit); - stream.readInt(&mSamplersPS[i].textureType); + Sampler sampler; + stream.readBool(&sampler.active); + stream.readInt(&sampler.logicalTextureUnit); + stream.readInt(&sampler.textureType); + mSamplersPS.push_back(sampler); } - - for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) + const unsigned int vsSamplerCount = stream.readInt(); + for (unsigned int i = 0; i < vsSamplerCount; ++i) { - stream.readBool(&mSamplersVS[i].active); - stream.readInt(&mSamplersVS[i].logicalTextureUnit); - stream.readInt(&mSamplersVS[i].textureType); + Sampler sampler; + stream.readBool(&sampler.active); + stream.readInt(&sampler.logicalTextureUnit); + stream.readInt(&sampler.textureType); + mSamplersVS.push_back(sampler); } stream.readInt(&mUsedVertexSamplerRange); @@ -1260,10 +1250,6 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) stream.readInt(&varying.semanticIndexCount); } - stream.readString(&mVertexHLSL); - - stream.readInt(&mVertexWorkarounds); - const unsigned int vertexShaderCount = stream.readInt(); for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++) { @@ -1280,7 +1266,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) unsigned int vertexShaderSize = stream.readInt(); const unsigned char *vertexShaderFunction = reinterpret_cast(binary) + stream.offset(); - rx::ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(reinterpret_cast(vertexShaderFunction), + rx::ShaderExecutable *shaderExecutable = mProgram->getRenderer()->loadExecutable(reinterpret_cast(vertexShaderFunction), vertexShaderSize, rx::SHADER_VERTEX, mTransformFeedbackLinkedVaryings, (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); @@ -1292,7 +1278,7 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) // generated converted input layout GLenum signature[MAX_VERTEX_ATTRIBS]; - mDynamicHLSL->getInputLayoutSignature(inputLayout, signature); + mProgram->getDynamicHLSL()->getInputLayoutSignature(inputLayout, signature); // add new binary mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable)); @@ -1300,20 +1286,6 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) stream.skip(vertexShaderSize); } - stream.readString(&mPixelHLSL); - stream.readInt(&mPixelWorkarounds); - stream.readBool(&mUsesFragDepth); - - 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 size_t pixelShaderCount = stream.readInt(); for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++) { @@ -1326,10 +1298,11 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) const size_t pixelShaderSize = stream.readInt(); const unsigned char *pixelShaderFunction = reinterpret_cast(binary) + stream.offset(); - rx::ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, - rx::SHADER_PIXEL, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); + rx::Renderer *renderer = mProgram->getRenderer(); + rx::ShaderExecutable *shaderExecutable = renderer->loadExecutable(pixelShaderFunction, pixelShaderSize, + rx::SHADER_PIXEL, mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); + if (!shaderExecutable) { infoLog.append("Could not create pixel shader."); @@ -1347,9 +1320,11 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) if (geometryShaderSize > 0) { const char *geometryShaderFunction = (const char*) binary + stream.offset(); - mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast(geometryShaderFunction), - geometryShaderSize, rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); + rx::Renderer *renderer = mProgram->getRenderer(); + mGeometryExecutable = renderer->loadExecutable(reinterpret_cast(geometryShaderFunction), + geometryShaderSize, rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); + if (!mGeometryExecutable) { infoLog.append("Could not create geometry shader."); @@ -1358,29 +1333,39 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) stream.skip(geometryShaderSize); } + if (!mProgram->load(infoLog, &stream)) + { + return false; + } + const char *ptr = (const char*) binary + stream.offset(); const GUID *binaryIdentifier = (const GUID *) ptr; ptr += sizeof(GUID); - GUID identifier = mRenderer->getAdapterIdentifier(); + GUID identifier = mProgram->getRenderer()->getAdapterIdentifier(); if (memcmp(&identifier, binaryIdentifier, sizeof(GUID)) != 0) { infoLog.append("Invalid program binary."); return false; } - initializeUniformStorage(); + mProgram->initializeUniformStorage(mUniforms); return true; #endif // #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD } -bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) +bool ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) { + if (binaryFormat) + { + *binaryFormat = mProgram->getBinaryFormat(); + } + BinaryOutputStream stream; - stream.writeInt(GL_PROGRAM_BINARY_ANGLE); + 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); @@ -1395,14 +1380,16 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.writeInt(mSemanticIndex[i]); } - for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) + 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); } - for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) + stream.writeInt(mSamplersVS.size()); + for (unsigned int i = 0; i < mSamplersVS.size(); ++i) { stream.writeInt(mSamplersVS[i].active); stream.writeInt(mSamplersVS[i].logicalTextureUnit); @@ -1477,9 +1464,6 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.writeInt(varying.semanticIndexCount); } - stream.writeString(mVertexHLSL); - stream.writeInt(mVertexWorkarounds); - stream.writeInt(mVertexExecutables.size()); for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++) { @@ -1501,20 +1485,6 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.writeBytes(vertexBlob, vertexShaderSize); } - stream.writeString(mPixelHLSL); - stream.writeInt(mPixelWorkarounds); - stream.writeInt(mUsesFragDepth); - - stream.writeInt(mPixelShaderKey.size()); - for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < mPixelShaderKey.size(); pixelShaderKeyIndex++) - { - const PixelShaderOuputVariable &variable = mPixelShaderKey[pixelShaderKeyIndex]; - stream.writeInt(variable.type); - stream.writeString(variable.name); - stream.writeString(variable.source); - stream.writeInt(variable.outputIndex); - } - stream.writeInt(mPixelExecutables.size()); for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++) { @@ -1543,7 +1513,17 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) stream.writeBytes(geometryBlob, geometryShaderSize); } - GUID identifier = mRenderer->getAdapterIdentifier(); + if (!mProgram->save(&stream)) + { + if (length) + { + *length = 0; + } + + return false; + } + + GUID identifier = mProgram->getRenderer()->getAdapterIdentifier(); GLsizei streamLength = stream.length(); const void *streamData = stream.data(); @@ -1583,7 +1563,7 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) GLint ProgramBinary::getLength() { GLint length; - if (save(NULL, INT_MAX, &length)) + if (save(NULL, NULL, INT_MAX, &length)) { return length; } @@ -1593,68 +1573,56 @@ GLint ProgramBinary::getLength() } } -bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader, - const std::vector& transformFeedbackVaryings, GLenum transformFeedbackBufferMode) +bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader, + const std::vector& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps) { if (!fragmentShader || !fragmentShader->isCompiled()) { return false; } + ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER); if (!vertexShader || !vertexShader->isCompiled()) { return false; } + ASSERT(vertexShader->getType() == GL_VERTEX_SHADER); reset(); - mTransformFeedbackBufferMode = transformFeedbackBufferMode; - - mShaderVersion = vertexShader->getShaderVersion(); + mSamplersPS.resize(caps.maxTextureImageUnits); + mSamplersVS.resize(caps.maxVertexTextureImageUnits); - mPixelHLSL = fragmentShader->getHLSL(); - mPixelWorkarounds = fragmentShader->getD3DWorkarounds(); - - mVertexHLSL = vertexShader->getHLSL(); - mVertexWorkarounds = vertexShader->getD3DWorkarounds(); + mTransformFeedbackBufferMode = transformFeedbackBufferMode; - // Map the varyings to the register file - VaryingPacking packing = { NULL }; - int registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShader, vertexShader, transformFeedbackVaryings); + rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); + rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); - if (registers < 0) - { - return false; - } + mShaderVersion = vertexShaderD3D->getShaderVersion(); - if (!linkVaryings(infoLog, fragmentShader, vertexShader)) - { - return false; - } - - mUsesPointSize = vertexShader->usesPointSize(); + int registers; std::vector linkedVaryings; - if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, registers, packing, mPixelHLSL, mVertexHLSL, - fragmentShader, vertexShader, transformFeedbackVaryings, - &linkedVaryings, &mOutputVariables, &mPixelShaderKey, &mUsesFragDepth)) + if (!mProgram->link(infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, ®isters, &linkedVaryings, &mOutputVariables)) { return false; } + mUsesPointSize = vertexShaderD3D->usesPointSize(); + bool success = true; - if (!linkAttributes(infoLog, attributeBindings, fragmentShader, vertexShader)) + if (!linkAttributes(infoLog, attributeBindings, vertexShader)) { success = false; } - if (!linkUniforms(infoLog, *vertexShader, *fragmentShader)) + if (!linkUniforms(infoLog, *vertexShader, *fragmentShader, caps)) { success = false; } // special case for gl_DepthRange, the only built-in uniform (also a struct) - if (vertexShader->usesDepthRange() || fragmentShader->usesDepthRange()) + if (vertexShaderD3D->usesDepthRange() || fragmentShaderD3D->usesDepthRange()) { const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo(); @@ -1663,13 +1631,13 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo)); } - if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader)) + if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, caps)) { success = false; } if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings, - transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings)) + transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings, caps)) { success = false; } @@ -1677,23 +1645,19 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin if (success) { VertexFormat defaultInputLayout[MAX_VERTEX_ATTRIBS]; - GetInputLayoutFromShader(vertexShader->activeAttributes(), defaultInputLayout); + GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout); rx::ShaderExecutable *defaultVertexExecutable = getVertexExecutableForInputLayout(defaultInputLayout); - std::vector defaultPixelOutput(IMPLEMENTATION_MAX_DRAW_BUFFERS); - for (size_t i = 0; i < defaultPixelOutput.size(); i++) - { - defaultPixelOutput[i] = (i == 0) ? GL_FLOAT : GL_NONE; - } + std::vector defaultPixelOutput = GetDefaultOutputLayoutFromShader(mProgram->getPixelShaderKey()); rx::ShaderExecutable *defaultPixelExecutable = getPixelExecutableForOutputLayout(defaultPixelOutput); if (usesGeometryShader()) { - std::string geometryHLSL = mDynamicHLSL->generateGeometryShaderHLSL(registers, fragmentShader, vertexShader); - mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY, - mTransformFeedbackLinkedVaryings, - (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), - rx::ANGLE_D3D_WORKAROUND_NONE); + std::string geometryHLSL = mProgram->getDynamicHLSL()->generateGeometryShaderHLSL(registers, fragmentShaderD3D, vertexShaderD3D); + mGeometryExecutable = mProgram->getRenderer()->compileToExecutable(infoLog, geometryHLSL.c_str(), + rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS), + rx::ANGLE_D3D_WORKAROUND_NONE); } if (!defaultVertexExecutable || !defaultPixelExecutable || (usesGeometryShader() && !mGeometryExecutable)) @@ -1708,15 +1672,20 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin } // Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices -bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader) +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 &activeAttributes = vertexShader->activeAttributes(); + const std::vector &shaderAttributes = vertexShader->getActiveAttributes(); // Link attributes that have a binding location - for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++) + for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) { - const sh::Attribute &attribute = activeAttributes[attributeIndex]; + const sh::Attribute &attribute = shaderAttributes[attributeIndex]; + + ASSERT(attribute.staticUse); + const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; mShaderAttributes[attributeIndex] = attribute; @@ -1755,9 +1724,12 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at } // Link attributes that don't have a binding location - for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++) + for (unsigned int attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) { - const sh::Attribute &attribute = activeAttributes[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 @@ -1778,7 +1750,7 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; ) { - int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name); + int index = vertexShaderD3D->getSemanticIndex(mLinkedAttribute[attributeIndex].name); int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type); for (int r = 0; r < rows; r++) @@ -1811,32 +1783,29 @@ bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::strin return false; } - return true; -} - -template -bool ProgramBinary::linkValidateFields(InfoLog &infoLog, const std::string &varName, const ShaderVarType &vertexVar, const ShaderVarType &fragmentVar) -{ - if (vertexVar.fields.size() != fragmentVar.fields.size()) + if (vertexVariable.fields.size() != fragmentVariable.fields.size()) { - infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", varName.c_str()); + infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", variableName.c_str()); return false; } - const unsigned int numMembers = vertexVar.fields.size(); + const unsigned int numMembers = vertexVariable.fields.size(); for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++) { - const ShaderVarType &vertexMember = vertexVar.fields[memberIndex]; - const ShaderVarType &fragmentMember = fragmentVar.fields[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, varName.c_str(), vertexMember.name.c_str(), fragmentMember.name.c_str()); + memberIndex, variableName.c_str(), + vertexMember.name.c_str(), fragmentMember.name.c_str()); return false; } - const std::string memberName = varName.substr(0, varName.length()-1) + "." + vertexVar.name + "'"; - if (!linkValidateVariables(infoLog, memberName, vertexMember, fragmentMember)) + const std::string memberName = variableName.substr(0, variableName.length() - 1) + "." + + vertexMember.name + "'"; + + if (!linkValidateVariablesBase(infoLog, vertexMember.name, vertexMember, fragmentMember, validatePrecision)) { return false; } @@ -1845,22 +1814,17 @@ bool ProgramBinary::linkValidateFields(InfoLog &infoLog, const std::string &varN return true; } -bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform) +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; } - if (!linkValidateFields(infoLog, uniformName, vertexUniform, fragmentUniform)) - { - return false; - } - return true; } -bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying) +bool ProgramBinary::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying) { if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false)) { @@ -1873,37 +1837,30 @@ bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &v return false; } - if (!linkValidateFields(infoLog, varyingName, vertexVarying, fragmentVarying)) - { - return false; - } - return true; } -bool ProgramBinary::linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform) +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.isRowMajorMatrix != fragmentUniform.isRowMajorMatrix) + if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout) { infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str()); return false; } - if (!linkValidateFields(infoLog, uniformName, vertexUniform, fragmentUniform)) - { - return false; - } - return true; } -bool ProgramBinary::linkUniforms(InfoLog &infoLog, const VertexShader &vertexShader, const FragmentShader &fragmentShader) +bool ProgramBinary::linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps) { + const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader.getImplementation()); + const rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader.getImplementation()); + const std::vector &vertexUniforms = vertexShader.getUniforms(); const std::vector &fragmentUniforms = fragmentShader.getUniforms(); @@ -1925,7 +1882,7 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const VertexShader &vertexSha { const sh::Uniform &vertexUniform = *entry->second; const std::string &uniformName = "uniform '" + vertexUniform.name + "'"; - if (!linkValidateVariables(infoLog, uniformName, vertexUniform, fragmentUniform)) + if (!linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform)) { return false; } @@ -1935,35 +1892,43 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const VertexShader &vertexSha for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++) { const sh::Uniform &uniform = vertexUniforms[uniformIndex]; - defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShader.getUniformRegister(uniform.name)); + + 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]; - defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShader.getUniformRegister(uniform.name)); + + if (uniform.staticUse) + { + defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name)); + } } - if (!indexUniforms(infoLog)) + if (!indexUniforms(infoLog, caps)) { return false; } - initializeUniformStorage(); + mProgram->initializeUniformStorage(mUniforms); return true; } void ProgramBinary::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister) { - ShShaderOutput outputType = Shader::getCompilerOutputType(shader); + ShShaderOutput outputType = rx::ShaderD3D::getCompilerOutputType(shader); sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType)); encoder.skipRegisters(uniformRegister); defineUniform(shader, uniform, uniform.name, &encoder); } -void ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &uniform, +void ProgramBinary::defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder) { if (uniform.isStruct()) @@ -1976,7 +1941,7 @@ void ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &uniform, for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++) { - const sh::Uniform &field = uniform.fields[fieldIndex]; + const sh::ShaderVariable &field = uniform.fields[fieldIndex]; const std::string &fieldFullName = (fullName + elementString + "." + field.name); defineUniform(shader, field, fieldFullName, encoder); @@ -2027,7 +1992,7 @@ void ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &uniform, } } -bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog) +bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps) { ASSERT(IsSampler(uniform.type)); ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX); @@ -2035,19 +2000,18 @@ bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &i if (uniform.vsRegisterIndex != GL_INVALID_INDEX) { if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS, - &mUsedVertexSamplerRange, mRenderer->getMaxVertexTextureImageUnits())) + &mUsedVertexSamplerRange)) { infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", - mRenderer->getMaxVertexTextureImageUnits()); + mSamplersVS.size()); return false; } - unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() + - mRenderer->getMaxVertexUniformVectors(); + unsigned int maxVertexVectors = mProgram->getRenderer()->getReservedVertexUniformVectors() + caps.maxVertexUniformVectors; if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors) { infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", - mRenderer->getMaxVertexUniformVectors()); + caps.maxVertexUniformVectors); return false; } } @@ -2055,19 +2019,18 @@ bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &i if (uniform.psRegisterIndex != GL_INVALID_INDEX) { if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS, - &mUsedPixelSamplerRange, MAX_TEXTURE_IMAGE_UNITS)) + &mUsedPixelSamplerRange)) { infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", - MAX_TEXTURE_IMAGE_UNITS); + mSamplersPS.size()); return false; } - unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() + - mRenderer->getMaxFragmentUniformVectors(); + unsigned int maxFragmentVectors = mProgram->getRenderer()->getReservedFragmentUniformVectors() + caps.maxFragmentUniformVectors; if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors) { infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", - mRenderer->getMaxFragmentUniformVectors()); + caps.maxFragmentUniformVectors); return false; } } @@ -2075,7 +2038,7 @@ bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &i return true; } -bool ProgramBinary::indexUniforms(InfoLog &infoLog) +bool ProgramBinary::indexUniforms(InfoLog &infoLog, const Caps &caps) { for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) { @@ -2083,7 +2046,7 @@ bool ProgramBinary::indexUniforms(InfoLog &infoLog) if (IsSampler(uniform.type)) { - if (!indexSamplerUniform(uniform, infoLog)) + if (!indexSamplerUniform(uniform, infoLog, caps)) { return false; } @@ -2101,20 +2064,20 @@ bool ProgramBinary::indexUniforms(InfoLog &infoLog) bool ProgramBinary::assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount, - Sampler *outArray, - GLuint *usedRange, - unsigned int limit) + std::vector &outSamplers, + GLuint *outUsedRange) { unsigned int samplerIndex = startSamplerIndex; do { - if (samplerIndex < limit) + if (samplerIndex < outSamplers.size()) { - outArray[samplerIndex].active = true; - outArray[samplerIndex].textureType = GetTextureType(samplerType); - outArray[samplerIndex].logicalTextureUnit = 0; - *usedRange = std::max(samplerIndex + 1, *usedRange); + Sampler& sampler = outSamplers[samplerIndex]; + sampler.active = true; + sampler.textureType = GetTextureType(samplerType); + sampler.logicalTextureUnit = 0; + *outUsedRange = std::max(samplerIndex + 1, *outUsedRange); } else { @@ -2163,8 +2126,8 @@ bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::Inter return false; } - std::string uniformName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; - if (!linkValidateVariables(infoLog, uniformName, vertexMember, fragmentMember)) + std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; + if (!linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember)) { return false; } @@ -2173,8 +2136,7 @@ bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::Inter return true; } -bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const VertexShader &vertexShader, - const FragmentShader &fragmentShader) +bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps) { const std::vector &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks(); const std::vector &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks(); @@ -2205,17 +2167,29 @@ bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const VertexShader &vert for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) { - if (!defineUniformBlock(infoLog, vertexShader, vertexInterfaceBlocks[blockIndex])) + const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex]; + + // Note: shared and std140 layouts are always considered active + if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) { - return false; + if (!defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps)) + { + return false; + } } } for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) { - if (!defineUniformBlock(infoLog, fragmentShader, fragmentInterfaceBlocks[blockIndex])) + const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex]; + + // Note: shared and std140 layouts are always considered active + if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED) { - return false; + if (!defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps)) + { + return false; + } } } @@ -2225,11 +2199,10 @@ bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const VertexShader &vert bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector &linkedVaryings, const std::vector &transformFeedbackVaryingNames, GLenum transformFeedbackBufferMode, - std::vector *outTransformFeedbackLinkedVaryings) const + std::vector *outTransformFeedbackLinkedVaryings, + const Caps &caps) const { size_t totalComponents = 0; - const size_t maxSeparateComponents = mRenderer->getMaxTransformFeedbackSeparateComponents(); - const size_t maxInterleavedComponents = mRenderer->getMaxTransformFeedbackInterleavedComponents(); // Gather the linked varyings that are used for transform feedback, they should all exist. outTransformFeedbackLinkedVaryings->clear(); @@ -2251,10 +2224,10 @@ bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, cons size_t componentCount = linkedVaryings[j].semanticIndexCount * 4; if (transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS && - componentCount > maxSeparateComponents) + componentCount > caps.maxTransformFeedbackSeparateComponents) { infoLog.append("Transform feedback varying's %s components (%u) exceed the maximum separate components (%u).", - linkedVaryings[j].name.c_str(), componentCount, maxSeparateComponents); + linkedVaryings[j].name.c_str(), componentCount, caps.maxTransformFeedbackSeparateComponents); return false; } @@ -2270,39 +2243,45 @@ bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, cons ASSERT(found); } - if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > maxInterleavedComponents) + if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > caps.maxTransformFeedbackInterleavedComponents) { infoLog.append("Transform feedback varying total components (%u) exceed the maximum interleaved components (%u).", - totalComponents, maxInterleavedComponents); + totalComponents, caps.maxTransformFeedbackInterleavedComponents); return false; } return true; } -void ProgramBinary::defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, - sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes) +template +void ProgramBinary::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 sh::InterfaceBlockField &field = fields[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); + defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes, rowMajorLayout); encoder->exitAggregateType(); } } else { - sh::BlockMemberInfo memberInfo = encoder->encodeInterfaceBlockField(field); + bool isRowMajorMatrix = (IsMatrixType(field.type) && inRowMajorLayout); + + sh::BlockMemberInfo memberInfo = encoder->encodeType(field.type, field.arraySize, isRowMajorMatrix); LinkedUniform *newUniform = new LinkedUniform(field.type, field.precision, fieldName, field.arraySize, blockIndex, memberInfo); @@ -2314,8 +2293,10 @@ void ProgramBinary::defineUniformBlockMembers(const std::vectorgetBlockSize(); @@ -2357,50 +2338,49 @@ bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, c } } - // 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 = shader.getInterfaceBlockRegister(interfaceBlock.name); - - for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++) + if (interfaceBlock.staticUse) { - UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement]; - ASSERT(uniformBlock->name == interfaceBlock.name); + // 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); - if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(), - interfaceBlockRegister + uniformBlockElement)) + for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++) { - return false; + UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement]; + ASSERT(uniformBlock->name == interfaceBlock.name); + + if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(), + interfaceBlockRegister + uniformBlockElement, caps)) + { + return false; + } } } return true; } -bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex) +bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps) { if (shader == GL_VERTEX_SHADER) { uniformBlock->vsRegisterIndex = registerIndex; - unsigned int maximumBlocks = mRenderer->getMaxVertexShaderUniformBuffers(); - - if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= maximumBlocks) + if (registerIndex - mProgram->getRenderer()->getReservedVertexUniformBuffers() >= caps.maxVertexUniformBlocks) { - infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", maximumBlocks); + 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; - unsigned int maximumBlocks = mRenderer->getMaxFragmentShaderUniformBuffers(); - - if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= maximumBlocks) + if (registerIndex - mProgram->getRenderer()->getReservedFragmentUniformBuffers() >= caps.maxFragmentUniformBlocks) { - infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", maximumBlocks); + infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", caps.maxFragmentUniformBlocks); return false; } } @@ -2670,10 +2650,10 @@ GLuint ProgramBinary::getActiveUniformBlockMaxLength() const return maxLength; } -void ProgramBinary::validate(InfoLog &infoLog) +void ProgramBinary::validate(InfoLog &infoLog, const Caps &caps) { applyUniforms(); - if (!validateSamplers(&infoLog)) + if (!validateSamplers(&infoLog, caps)) { mValidated = false; } @@ -2683,20 +2663,14 @@ void ProgramBinary::validate(InfoLog &infoLog) } } -bool ProgramBinary::validateSamplers(InfoLog *infoLog) +bool ProgramBinary::validateSamplers(InfoLog *infoLog, const 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(); - const unsigned int maxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits(); - TextureType textureUnitType[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; - - for (unsigned int i = 0; i < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; ++i) - { - textureUnitType[i] = TEXTURE_UNKNOWN; - } + std::vector textureUnitTypes(caps.maxCombinedTextureImageUnits, GL_NONE); for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i) { @@ -2704,19 +2678,19 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) { unsigned int unit = mSamplersPS[i].logicalTextureUnit; - if (unit >= maxCombinedTextureImageUnits) + if (unit >= textureUnitTypes.size()) { if (infoLog) { - infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); + infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size()); } return false; } - if (textureUnitType[unit] != TEXTURE_UNKNOWN) + if (textureUnitTypes[unit] != GL_NONE) { - if (mSamplersPS[i].textureType != textureUnitType[unit]) + if (mSamplersPS[i].textureType != textureUnitTypes[unit]) { if (infoLog) { @@ -2728,7 +2702,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) } else { - textureUnitType[unit] = mSamplersPS[i].textureType; + textureUnitTypes[unit] = mSamplersPS[i].textureType; } } } @@ -2739,19 +2713,19 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) { unsigned int unit = mSamplersVS[i].logicalTextureUnit; - if (unit >= maxCombinedTextureImageUnits) + if (unit >= textureUnitTypes.size()) { if (infoLog) { - infoLog->append("Sampler uniform (%d) exceeds IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, maxCombinedTextureImageUnits); + infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size()); } return false; } - if (textureUnitType[unit] != TEXTURE_UNKNOWN) + if (textureUnitTypes[unit] != GL_NONE) { - if (mSamplersVS[i].textureType != textureUnitType[unit]) + if (mSamplersVS[i].textureType != textureUnitTypes[unit]) { if (infoLog) { @@ -2763,7 +2737,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) } else { - textureUnitType[unit] = mSamplersVS[i].textureType; + textureUnitTypes[unit] = mSamplersVS[i].textureType; } } } @@ -2771,7 +2745,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) return true; } -ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(TEXTURE_2D) +ProgramBinary::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureType(GL_TEXTURE_2D) { } @@ -2819,42 +2793,9 @@ void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MA } } -void ProgramBinary::initializeUniformStorage() -{ - // Compute total default block size - unsigned int vertexRegisters = 0; - unsigned int fragmentRegisters = 0; - for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) - { - const LinkedUniform &uniform = *mUniforms[uniformIndex]; - - if (!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); -} - void ProgramBinary::reset() { - mVertexHLSL.clear(); - mVertexWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE; SafeDeleteContainer(mVertexExecutables); - - mPixelHLSL.clear(); - mPixelWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE; - mUsesFragDepth = false; - mPixelShaderKey.clear(); SafeDeleteContainer(mPixelExecutables); SafeDelete(mGeometryExecutable); @@ -2862,14 +2803,9 @@ void ProgramBinary::reset() mTransformFeedbackBufferMode = GL_NONE; mTransformFeedbackLinkedVaryings.clear(); - for (size_t i = 0; i < ArraySize(mSamplersPS); i++) - { - mSamplersPS[i] = Sampler(); - } - for (size_t i = 0; i < ArraySize(mSamplersVS); i++) - { - mSamplersVS[i] = Sampler(); - } + mSamplersPS.clear(); + mSamplersVS.clear(); + mUsedVertexSamplerRange = 0; mUsedPixelSamplerRange = 0; mUsesPointSize = false; @@ -2880,8 +2816,8 @@ void ProgramBinary::reset() SafeDeleteContainer(mUniformBlocks); mUniformIndex.clear(); mOutputVariables.clear(); - SafeDelete(mVertexUniformStorage); - SafeDelete(mFragmentUniformStorage); + + mProgram->reset(); mValidated = false; } diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h index f0fc431021..ad470d417b 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h @@ -10,11 +10,6 @@ #ifndef LIBGLESV2_PROGRAM_BINARY_H_ #define LIBGLESV2_PROGRAM_BINARY_H_ -#include "angle_gl.h" - -#include -#include - #include "common/RefCountObject.h" #include "angletypes.h" #include "common/mathutil.h" @@ -22,25 +17,43 @@ #include "libGLESv2/Shader.h" #include "libGLESv2/Constants.h" #include "libGLESv2/renderer/d3d/VertexDataManager.h" -#include "libGLESv2/DynamicHLSL.h" +#include "libGLESv2/renderer/d3d/DynamicHLSL.h" + +#include "angle_gl.h" + +#include +#include + +// TODO(jmadill): place this in workarounds library +#define ANGLE_WORKAROUND_ENABLED 1 +#define ANGLE_WORKAROUND_DISABLED 2 +#define ANGLE_MRT_PERF_WORKAROUND ANGLE_WORKAROUND_ENABLED namespace sh { class HLSLBlockEncoder; } +#include +#include +#include + +#include +#include + namespace rx { class ShaderExecutable; class Renderer; struct TranslatedAttribute; class UniformStorage; +class ProgramImpl; } namespace gl { -class FragmentShader; -class VertexShader; +struct Caps; +class Shader; class InfoLog; class AttributeBindings; class Buffer; @@ -82,9 +95,12 @@ struct LinkedVarying class ProgramBinary : public RefCountObject { public: - explicit ProgramBinary(rx::Renderer *renderer); + explicit ProgramBinary(rx::ProgramImpl *impl); ~ProgramBinary(); + rx::ProgramImpl *getImplementation() { return mProgram; } + const rx::ProgramImpl *getImplementation() const { return mProgram; } + rx::ShaderExecutable *getPixelExecutableForFramebuffer(const Framebuffer *fbo); rx::ShaderExecutable *getPixelExecutableForOutputLayout(const std::vector &outputLayout); rx::ShaderExecutable *getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]); @@ -93,8 +109,8 @@ class ProgramBinary : public RefCountObject GLuint getAttributeLocation(const char *name); int getSemanticIndex(int attributeIndex); - GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex); - TextureType getSamplerTextureType(SamplerType type, unsigned int samplerIndex); + GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps); + GLenum getSamplerTextureType(SamplerType type, unsigned int samplerIndex); GLint getUsedSamplerRange(SamplerType type); bool usesPointSize() const; bool usesPointSpriteEmulation() const; @@ -125,20 +141,21 @@ class ProgramBinary : public RefCountObject void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); - bool getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params); - bool getUniformiv(GLint location, GLsizei *bufSize, GLint *params); - bool getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params); + void getUniformfv(GLint location, GLfloat *params); + void getUniformiv(GLint location, GLint *params); + void getUniformuiv(GLint location, GLuint *params); void dirtyAllUniforms(); - void applyUniforms(); - bool applyUniformBuffers(const std::vector boundBuffers); - bool load(InfoLog &infoLog, const void *binary, GLsizei length); - bool save(void* binary, GLsizei bufSize, GLsizei *length); + Error applyUniforms(); + Error applyUniformBuffers(const std::vector boundBuffers, const Caps &caps); + + bool load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length); + bool save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length); GLint getLength(); - bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader, - const std::vector& transformFeedbackVaryings, GLenum transformFeedbackBufferMode); + bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, Shader *fragmentShader, Shader *vertexShader, + const std::vector& transformFeedbackVaryings, GLenum transformFeedbackBufferMode, const Caps &caps); void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; @@ -165,8 +182,8 @@ class ProgramBinary : public RefCountObject const LinkedVarying &getTransformFeedbackVarying(size_t idx) const; GLenum getTransformFeedbackBufferMode() const; - void validate(InfoLog &infoLog); - bool validateSamplers(InfoLog *infoLog); + void validate(InfoLog &infoLog, const Caps &caps); + bool validateSamplers(InfoLog *infoLog, const Caps &caps); bool isValidated() const; void updateSamplerMapping(); @@ -177,8 +194,8 @@ class ProgramBinary : public RefCountObject void sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const; const std::vector &getUniforms() const { return mUniforms; } - const rx::UniformStorage &getVertexUniformStorage() const { return *mVertexUniformStorage; } - const rx::UniformStorage &getFragmentUniformStorage() const { return *mFragmentUniformStorage; } + + static bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader); private: DISALLOW_COPY_AND_ASSIGN(ProgramBinary); @@ -189,40 +206,43 @@ class ProgramBinary : public RefCountObject bool active; GLint logicalTextureUnit; - TextureType textureType; + GLenum textureType; }; void reset(); - bool linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader); - bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader); + bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader); - template - bool linkValidateFields(InfoLog &infoLog, const std::string &varName, const ShaderVarType &vertexVar, const ShaderVarType &fragmentVar); - bool linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable, const sh::ShaderVariable &fragmentVariable, bool validatePrecision); + static bool linkValidateVariablesBase(InfoLog &infoLog, + const std::string &variableName, + const sh::ShaderVariable &vertexVariable, + const sh::ShaderVariable &fragmentVariable, + bool validatePrecision); - bool linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform); - bool linkValidateVariables(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying); - bool linkValidateVariables(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform); - bool linkUniforms(InfoLog &infoLog, const VertexShader &vertexShader, const FragmentShader &fragmentShader); + static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform); + static bool linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying); + static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform); + bool linkUniforms(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister); - void defineUniform(GLenum shader, const sh::Uniform &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder); - bool indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog); - bool indexUniforms(InfoLog &infoLog); + void defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName, sh::HLSLBlockEncoder *encoder); + bool indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog, const Caps &caps); + bool indexUniforms(InfoLog &infoLog, const Caps &caps); static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount, - Sampler *outArray, GLuint *usedRange, unsigned int limit); + std::vector &outSamplers, GLuint *outUsedRange); bool areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock); - bool linkUniformBlocks(InfoLog &infoLog, const VertexShader &vertexShader, const FragmentShader &fragmentShader); + bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps); bool gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector &linkedVaryings, const std::vector &transformFeedbackVaryingNames, GLenum transformFeedbackBufferMode, - std::vector *outTransformFeedbackLinkedVaryings) const; - void defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, - sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes); - bool defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock); - bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex); - void defineOutputVariables(FragmentShader *fragmentShader); - void initializeUniformStorage(); + std::vector *outTransformFeedbackLinkedVaryings, + const Caps &caps) const; + template + void defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, + sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes, + bool inRowMajorLayout); + bool defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock, const Caps &caps); + bool assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex, const Caps &caps); + void defineOutputVariables(Shader *fragmentShader); template void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType); @@ -231,7 +251,7 @@ class ProgramBinary : public RefCountObject void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType); template - bool getUniformv(GLint location, GLsizei *bufSize, T *params, GLenum uniformType); + void getUniformv(GLint location, T *params, GLenum uniformType); class VertexExecutable { @@ -259,8 +279,7 @@ class ProgramBinary : public RefCountObject PixelExecutable(const std::vector &outputSignature, rx::ShaderExecutable *shaderExecutable); ~PixelExecutable(); - // FIXME(geofflang): Work around NVIDIA driver bug by repacking buffers - bool matchesSignature(const std::vector &signature) const { return true; /* mOutputSignature == signature; */ } + bool matchesSignature(const std::vector &signature) const { return mOutputSignature == signature; } const std::vector &outputSignature() const { return mOutputSignature; } rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } @@ -270,17 +289,9 @@ class ProgramBinary : public RefCountObject rx::ShaderExecutable *mShaderExecutable; }; - rx::Renderer *const mRenderer; - DynamicHLSL *mDynamicHLSL; + rx::ProgramImpl *mProgram; - std::string mVertexHLSL; - rx::D3DWorkaroundType mVertexWorkarounds; std::vector mVertexExecutables; - - std::string mPixelHLSL; - rx::D3DWorkaroundType mPixelWorkarounds; - bool mUsesFragDepth; - std::vector mPixelShaderKey; std::vector mPixelExecutables; rx::ShaderExecutable *mGeometryExecutable; @@ -293,8 +304,8 @@ class ProgramBinary : public RefCountObject GLenum mTransformFeedbackBufferMode; std::vector mTransformFeedbackLinkedVaryings; - Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS]; - Sampler mSamplersVS[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + std::vector mSamplersPS; + std::vector mSamplersVS; GLuint mUsedVertexSamplerRange; GLuint mUsedPixelSamplerRange; bool mUsesPointSize; @@ -305,8 +316,6 @@ class ProgramBinary : public RefCountObject std::vector mUniformBlocks; std::vector mUniformIndex; std::map mOutputVariables; - rx::UniformStorage *mVertexUniformStorage; - rx::UniformStorage *mFragmentUniformStorage; bool mValidated; diff --git a/src/3rdparty/angle/src/libGLESv2/Query.cpp b/src/3rdparty/angle/src/libGLESv2/Query.cpp index 6546d06c34..4ee3525509 100644 --- a/src/3rdparty/angle/src/libGLESv2/Query.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Query.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -9,39 +8,38 @@ #include "libGLESv2/Query.h" #include "libGLESv2/renderer/QueryImpl.h" -#include "libGLESv2/renderer/Renderer.h" namespace gl { - -Query::Query(rx::Renderer *renderer, GLenum type, GLuint id) : RefCountObject(id) -{ - mQuery = renderer->createQuery(type); +Query::Query(rx::QueryImpl *impl, GLuint id) + : RefCountObject(id), + mQuery(impl) +{ } Query::~Query() { - delete mQuery; + SafeDelete(mQuery); } -void Query::begin() +Error Query::begin() { - mQuery->begin(); + return mQuery->begin(); } -void Query::end() +Error Query::end() { - mQuery->end(); + return mQuery->end(); } -GLuint Query::getResult() +Error Query::getResult(GLuint *params) { - return mQuery->getResult(); + return mQuery->getResult(params); } -GLboolean Query::isResultAvailable() +Error Query::isResultAvailable(GLuint *available) { - return mQuery->isResultAvailable(); + return mQuery->isResultAvailable(available); } GLenum Query::getType() const @@ -49,9 +47,4 @@ GLenum Query::getType() const return mQuery->getType(); } -bool Query::isStarted() const -{ - return mQuery->isStarted(); -} - } diff --git a/src/3rdparty/angle/src/libGLESv2/Query.h b/src/3rdparty/angle/src/libGLESv2/Query.h index a4726a8e73..a7ec404f85 100644 --- a/src/3rdparty/angle/src/libGLESv2/Query.h +++ b/src/3rdparty/angle/src/libGLESv2/Query.h @@ -9,14 +9,14 @@ #ifndef LIBGLESV2_QUERY_H_ #define LIBGLESV2_QUERY_H_ -#include "angle_gl.h" - +#include "libGLESv2/Error.h" #include "common/angleutils.h" #include "common/RefCountObject.h" +#include "angle_gl.h" + namespace rx { -class Renderer; class QueryImpl; } @@ -26,17 +26,16 @@ namespace gl class Query : public RefCountObject { public: - Query(rx::Renderer *renderer, GLenum type, GLuint id); + Query(rx::QueryImpl *impl, GLuint id); virtual ~Query(); - void begin(); - void end(); + Error begin(); + Error end(); - GLuint getResult(); - GLboolean isResultAvailable(); + Error getResult(GLuint *params); + Error isResultAvailable(GLuint *available); GLenum getType() const; - bool isStarted() const; private: DISALLOW_COPY_AND_ASSIGN(Query); diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp index d4bfaf27a1..9406fce58d 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -10,13 +9,13 @@ // objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. #include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/renderer/RenderTarget.h" - #include "libGLESv2/Texture.h" -#include "libGLESv2/renderer/Renderer.h" -#include "common/utilities.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/FramebufferAttachment.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/RenderTarget.h" + +#include "common/utilities.h" namespace gl { @@ -29,6 +28,11 @@ Renderbuffer::Renderbuffer(GLuint id, RenderbufferStorage *newStorage) ASSERT(mStorage); } +Renderbuffer::~Renderbuffer() +{ + SafeDelete(mStorage); +} + void Renderbuffer::setStorage(RenderbufferStorage *newStorage) { ASSERT(newStorage); @@ -75,32 +79,32 @@ GLsizei Renderbuffer::getSamples() const GLuint Renderbuffer::getRedSize() const { - return gl::GetRedBits(getActualFormat()); + return GetInternalFormatInfo(getActualFormat()).redBits; } GLuint Renderbuffer::getGreenSize() const { - return gl::GetGreenBits(getActualFormat()); + return GetInternalFormatInfo(getActualFormat()).greenBits; } GLuint Renderbuffer::getBlueSize() const { - return gl::GetBlueBits(getActualFormat()); + return GetInternalFormatInfo(getActualFormat()).blueBits; } GLuint Renderbuffer::getAlphaSize() const { - return gl::GetAlphaBits(getActualFormat()); + return GetInternalFormatInfo(getActualFormat()).alphaBits; } GLuint Renderbuffer::getDepthSize() const { - return gl::GetDepthBits(getActualFormat()); + return GetInternalFormatInfo(getActualFormat()).depthBits; } GLuint Renderbuffer::getStencilSize() const { - return gl::GetStencilBits(getActualFormat()); + return GetInternalFormatInfo(getActualFormat()).stencilBits; } RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerials(1)) @@ -121,11 +125,6 @@ rx::RenderTarget *RenderbufferStorage::getRenderTarget() return NULL; } -rx::RenderTarget *RenderbufferStorage::getDepthStencil() -{ - return NULL; -} - GLsizei RenderbufferStorage::getWidth() const { return mWidth; @@ -156,7 +155,7 @@ unsigned int RenderbufferStorage::getSerial() const return mSerial; } -unsigned int RenderbufferStorage::issueSerials(GLuint count) +unsigned int RenderbufferStorage::issueSerials(unsigned int count) { unsigned int firstSerial = mCurrentSerial; mCurrentSerial += count; @@ -247,7 +246,7 @@ DepthStencilbuffer::~DepthStencilbuffer() } } -rx::RenderTarget *DepthStencilbuffer::getDepthStencil() +rx::RenderTarget *DepthStencilbuffer::getRenderTarget() { return mDepthStencil; } diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h index e2d0c6b0fd..71bcb0e1f8 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h @@ -39,6 +39,7 @@ class Renderbuffer : public RefCountObject { public: Renderbuffer(GLuint id, RenderbufferStorage *newStorage); + virtual ~Renderbuffer(); void setStorage(RenderbufferStorage *newStorage); RenderbufferStorage *getStorage(); @@ -70,7 +71,6 @@ class RenderbufferStorage virtual ~RenderbufferStorage() = 0; virtual rx::RenderTarget *getRenderTarget(); - virtual rx::RenderTarget *getDepthStencil(); virtual GLsizei getWidth() const; virtual GLsizei getHeight() const; @@ -83,7 +83,7 @@ class RenderbufferStorage virtual bool isTexture() const; virtual unsigned int getTextureSerial() const; - static unsigned int issueSerials(GLuint count); + static unsigned int issueSerials(unsigned int count); protected: GLsizei mWidth; @@ -124,7 +124,7 @@ class DepthStencilbuffer : public RenderbufferStorage ~DepthStencilbuffer(); - virtual rx::RenderTarget *getDepthStencil(); + virtual rx::RenderTarget *getRenderTarget(); protected: rx::RenderTarget *mDepthStencil; diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp index 3606532404..9121de1750 100644 --- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -93,13 +92,9 @@ GLuint ResourceManager::createShader(GLenum type) { GLuint handle = mProgramShaderHandleAllocator.allocate(); - if (type == GL_VERTEX_SHADER) + if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER) { - mShaderMap[handle] = new VertexShader(this, mRenderer, handle); - } - else if (type == GL_FRAGMENT_SHADER) - { - mShaderMap[handle] = new FragmentShader(this, mRenderer, handle); + mShaderMap[handle] = new Shader(this, mRenderer->createShader(type), type, handle); } else UNREACHABLE(); @@ -151,7 +146,9 @@ GLuint ResourceManager::createFenceSync() { GLuint handle = mFenceSyncHandleAllocator.allocate(); - mFenceSyncMap[handle] = new FenceSync(mRenderer, handle); + FenceSync *fenceSync = new FenceSync(mRenderer, handle); + fenceSync->addRef(); + mFenceSyncMap[handle] = fenceSync; return handle; } @@ -369,27 +366,27 @@ void ResourceManager::checkBufferAllocation(unsigned int buffer) } } -void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type) +void ResourceManager::checkTextureAllocation(GLuint texture, GLenum type) { if (!getTexture(texture) && texture != 0) { Texture *textureObject; - if (type == TEXTURE_2D) + if (type == GL_TEXTURE_2D) { - textureObject = new Texture2D(mRenderer->createTexture2D(), texture); + textureObject = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), texture); } - else if (type == TEXTURE_CUBE) + else if (type == GL_TEXTURE_CUBE_MAP) { - textureObject = new TextureCubeMap(mRenderer->createTextureCube(), texture); + textureObject = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), texture); } - else if (type == TEXTURE_3D) + else if (type == GL_TEXTURE_3D) { - textureObject = new Texture3D(mRenderer->createTexture3D(), texture); + textureObject = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), texture); } - else if (type == TEXTURE_2D_ARRAY) + else if (type == GL_TEXTURE_2D_ARRAY) { - textureObject = new Texture2DArray(mRenderer->createTexture2DArray(), texture); + textureObject = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), texture); } else { diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h index d646c0d3cf..7d53bd4854 100644 --- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h +++ b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h @@ -10,14 +10,14 @@ #ifndef LIBGLESV2_RESOURCEMANAGER_H_ #define LIBGLESV2_RESOURCEMANAGER_H_ -#include "angle_gl.h" - -#include - #include "common/angleutils.h" #include "libGLESv2/angletypes.h" #include "libGLESv2/HandleAllocator.h" +#include "angle_gl.h" + +#include + namespace rx { class Renderer; @@ -65,11 +65,11 @@ class ResourceManager 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, TextureType type); + void checkTextureAllocation(GLuint texture, GLenum type); void checkRenderbufferAllocation(GLuint renderbuffer); void checkSamplerAllocation(GLuint sampler); diff --git a/src/3rdparty/angle/src/libGLESv2/Sampler.cpp b/src/3rdparty/angle/src/libGLESv2/Sampler.cpp index ed6e29f89e..b906e65557 100644 --- a/src/3rdparty/angle/src/libGLESv2/Sampler.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Sampler.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp index eda0298e87..e3da2b1a9e 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Shader.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -10,27 +9,30 @@ // functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84. #include "libGLESv2/Shader.h" - -#include "GLSLANG/ShaderLang.h" -#include "common/utilities.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 { -void *Shader::mFragmentCompiler = NULL; -void *Shader::mVertexCompiler = NULL; -Shader::Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) - : mHandle(handle), mRenderer(renderer), mResourceManager(manager) +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) { - uncompile(); - initializeCompiler(); - - mRefCount = 0; - mDeleteStatus = false; - mShaderVersion = 100; + ASSERT(impl); } Shader::~Shader() @@ -56,7 +58,7 @@ void Shader::setSource(GLsizei count, const char *const *string, const GLint *le int Shader::getInfoLogLength() const { - return mInfoLog.empty() ? 0 : (mInfoLog.length() + 1); + return mShader->getInfoLog().empty() ? 0 : (mShader->getInfoLog().length() + 1); } void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const @@ -65,8 +67,8 @@ void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const if (bufSize > 0) { - index = std::min(bufSize - 1, static_cast(mInfoLog.length())); - memcpy(infoLog, mInfoLog.c_str(), index); + index = std::min(bufSize - 1, static_cast(mShader->getInfoLog().length())); + memcpy(infoLog, mShader->getInfoLog().c_str(), index); infoLog[index] = '\0'; } @@ -84,10 +86,10 @@ int Shader::getSourceLength() const int Shader::getTranslatedSourceLength() const { - return mHlsl.empty() ? 0 : (mHlsl.length() + 1); + return mShader->getTranslatedSource().empty() ? 0 : (mShader->getTranslatedSource().length() + 1); } -void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) const +void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) { int index = 0; @@ -112,44 +114,12 @@ void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const { - getSourceImpl(mHlsl, bufSize, length, buffer); + getSourceImpl(mShader->getTranslatedSource(), bufSize, length, buffer); } -unsigned int Shader::getUniformRegister(const std::string &uniformName) const +void Shader::compile() { - ASSERT(mUniformRegisterMap.count(uniformName) > 0); - return mUniformRegisterMap.find(uniformName)->second; -} - -unsigned int Shader::getInterfaceBlockRegister(const std::string &blockName) const -{ - ASSERT(mInterfaceBlockRegisterMap.count(blockName) > 0); - return mInterfaceBlockRegisterMap.find(blockName)->second; -} - -const std::vector &Shader::getUniforms() const -{ - return mActiveUniforms; -} - -const std::vector &Shader::getInterfaceBlocks() const -{ - return mActiveInterfaceBlocks; -} - -std::vector &Shader::getVaryings() -{ - return mVaryings; -} - -bool Shader::isCompiled() const -{ - return !mHlsl.empty(); -} - -const std::string &Shader::getHLSL() const -{ - return mHlsl; + mCompiled = mShader->compile(mSource); } void Shader::addRef() @@ -182,412 +152,54 @@ void Shader::flagForDeletion() mDeleteStatus = true; } -// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler) -void Shader::initializeCompiler() -{ - if (!mFragmentCompiler) - { - int result = ShInitialize(); - - if (result) - { - ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT; - - ShBuiltInResources resources; - ShInitBuiltInResources(&resources); - - // TODO(geofflang): use context's caps - const gl::Caps &caps = mRenderer->getRendererCaps(); - const gl::Extensions &extensions = mRenderer->getRendererExtensions(); - - resources.MaxVertexAttribs = MAX_VERTEX_ATTRIBS; - resources.MaxVertexUniformVectors = mRenderer->getMaxVertexUniformVectors(); - resources.MaxVaryingVectors = mRenderer->getMaxVaryingVectors(); - resources.MaxVertexTextureImageUnits = mRenderer->getMaxVertexTextureImageUnits(); - resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits(); - resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; - resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors(); - 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 = mRenderer->getMaxVaryingVectors(); - resources.MaxFragmentInputVectors = mRenderer->getMaxVaryingVectors(); - resources.MinProgramTexelOffset = -8; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE - resources.MaxProgramTexelOffset = 7; // D3D10_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE - - mFragmentCompiler = ShConstructCompiler(GL_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); - mVertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); - } - } -} - -void Shader::releaseCompiler() +const std::vector &Shader::getVaryings() const { - ShDestruct(mFragmentCompiler); - ShDestruct(mVertexCompiler); - - mFragmentCompiler = NULL; - mVertexCompiler = NULL; - - ShFinalize(); + return mShader->getVaryings(); } -void Shader::parseVaryings(void *compiler) -{ - if (!mHlsl.empty()) - { - std::vector *activeVaryings; - ShGetInfoPointer(compiler, SH_ACTIVE_VARYINGS_ARRAY, reinterpret_cast(&activeVaryings)); - - for (size_t varyingIndex = 0; varyingIndex < activeVaryings->size(); varyingIndex++) - { - mVaryings.push_back(PackedVarying((*activeVaryings)[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 Shader::resetVaryingsRegisterAssignment() -{ - for (unsigned int varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++) - { - mVaryings[varyingIndex].resetRegisterAssignment(); - } -} - -// initialize/clean up previous state -void Shader::uncompile() -{ - // set by compileToHLSL - mHlsl.clear(); - mInfoLog.clear(); - - // set by parseVaryings - mVaryings.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; - - mActiveUniforms.clear(); - mActiveInterfaceBlocks.clear(); -} - -void Shader::compileToHLSL(void *compiler) -{ - // ensure the compiler is loaded - initializeCompiler(); - - int compileOptions = SH_OBJECT_CODE; - std::string sourcePath; - if (perfActive()) - { - sourcePath = getTempPath(); - writeFile(sourcePath.c_str(), mSource.c_str(), mSource.length()); - compileOptions |= SH_LINE_DIRECTIVES; - } - - int result; - if (sourcePath.empty()) - { - const char* sourceStrings[] = - { - mSource.c_str(), - }; - - result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions); - } - else - { - const char* sourceStrings[] = - { - sourcePath.c_str(), - mSource.c_str(), - }; - - result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH); - } - - size_t shaderVersion = 100; - ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion); - - mShaderVersion = static_cast(shaderVersion); - - if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3) - { - mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts"; - TRACE("\n%s", mInfoLog.c_str()); - } - else if (result) - { - size_t objCodeLen = 0; - ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); - - char* outputHLSL = new char[objCodeLen]; - ShGetObjectCode(compiler, outputHLSL); - -#ifdef _DEBUG - std::ostringstream hlslStream; - hlslStream << "// GLSL\n"; - hlslStream << "//\n"; - - size_t curPos = 0; - while (curPos != std::string::npos) - { - size_t nextLine = mSource.find("\n", curPos); - size_t len = (nextLine == std::string::npos) ? std::string::npos : (nextLine - curPos + 1); - - hlslStream << "// " << mSource.substr(curPos, len); - - curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1); - } - hlslStream << "\n\n"; - hlslStream << outputHLSL; - mHlsl = hlslStream.str(); -#else - mHlsl = outputHLSL; -#endif - - delete[] outputHLSL; - - void *activeUniforms; - ShGetInfoPointer(compiler, SH_ACTIVE_UNIFORMS_ARRAY, &activeUniforms); - mActiveUniforms = *(std::vector*)activeUniforms; - - for (size_t uniformIndex = 0; uniformIndex < mActiveUniforms.size(); uniformIndex++) - { - const sh::Uniform &uniform = mActiveUniforms[uniformIndex]; - - unsigned int index = -1; - bool result = ShGetUniformRegister(compiler, uniform.name.c_str(), &index); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(result); - - mUniformRegisterMap[uniform.name] = index; - } - - void *activeInterfaceBlocks; - ShGetInfoPointer(compiler, SH_ACTIVE_INTERFACE_BLOCKS_ARRAY, &activeInterfaceBlocks); - mActiveInterfaceBlocks = *(std::vector*)activeInterfaceBlocks; - - for (size_t blockIndex = 0; blockIndex < mActiveInterfaceBlocks.size(); blockIndex++) - { - const sh::InterfaceBlock &interfaceBlock = mActiveInterfaceBlocks[blockIndex]; - - unsigned int index = -1; - bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name.c_str(), &index); - UNUSED_ASSERTION_VARIABLE(result); - ASSERT(result); - - mInterfaceBlockRegisterMap[interfaceBlock.name] = index; - } - } - else - { - size_t infoLogLen = 0; - ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen); - - char* infoLog = new char[infoLogLen]; - ShGetInfoLog(compiler, infoLog); - mInfoLog = infoLog; - - TRACE("\n%s", mInfoLog.c_str()); - } -} - -rx::D3DWorkaroundType Shader::getD3DWorkarounds() const -{ - if (mUsesDiscardRewriting) - { - // ANGLE issue 486: - // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization - return rx::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 rx::ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION; - } - - return rx::ANGLE_D3D_WORKAROUND_NONE; -} - -// true if varying x has a higher priority in packing than y -bool Shader::compareVarying(const PackedVarying &x, const 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); -} - -int Shader::getShaderVersion() const -{ - return mShaderVersion; -} - -VertexShader::VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) - : Shader(manager, renderer, handle) -{ -} - -VertexShader::~VertexShader() -{ -} - -GLenum VertexShader::getType() const -{ - return GL_VERTEX_SHADER; -} - -void VertexShader::uncompile() -{ - Shader::uncompile(); - - // set by ParseAttributes - mActiveAttributes.clear(); -} - -void VertexShader::compile() -{ - uncompile(); - - compileToHLSL(mVertexCompiler); - parseAttributes(); - parseVaryings(mVertexCompiler); -} - -int VertexShader::getSemanticIndex(const std::string &attributeName) +const std::vector &Shader::getUniforms() const { - if (!attributeName.empty()) - { - int semanticIndex = 0; - for (unsigned int attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++) - { - const sh::ShaderVariable &attribute = mActiveAttributes[attributeIndex]; - - if (attribute.name == attributeName) - { - return semanticIndex; - } - - semanticIndex += VariableRegisterCount(attribute.type); - } - } - - return -1; + return mShader->getUniforms(); } -void VertexShader::parseAttributes() +const std::vector &Shader::getInterfaceBlocks() const { - const std::string &hlsl = getHLSL(); - if (!hlsl.empty()) - { - void *activeAttributes; - ShGetInfoPointer(mVertexCompiler, SH_ACTIVE_ATTRIBUTES_ARRAY, &activeAttributes); - mActiveAttributes = *(std::vector*)activeAttributes; - } + return mShader->getInterfaceBlocks(); } -FragmentShader::FragmentShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) - : Shader(manager, renderer, handle) +const std::vector &Shader::getActiveAttributes() const { + return mShader->getActiveAttributes(); } -FragmentShader::~FragmentShader() +const std::vector &Shader::getActiveOutputVariables() const { + return mShader->getActiveOutputVariables(); } -GLenum FragmentShader::getType() const +std::vector &Shader::getVaryings() { - return GL_FRAGMENT_SHADER; + return mShader->getVaryings(); } -void FragmentShader::compile() +std::vector &Shader::getUniforms() { - uncompile(); - - compileToHLSL(mFragmentCompiler); - parseVaryings(mFragmentCompiler); - std::sort(mVaryings.begin(), mVaryings.end(), compareVarying); - - const std::string &hlsl = getHLSL(); - if (!hlsl.empty()) - { - void *activeOutputVariables; - ShGetInfoPointer(mFragmentCompiler, SH_ACTIVE_OUTPUT_VARIABLES_ARRAY, &activeOutputVariables); - mActiveOutputVariables = *(std::vector*)activeOutputVariables; - } + return mShader->getUniforms(); } -void FragmentShader::uncompile() +std::vector &Shader::getInterfaceBlocks() { - Shader::uncompile(); - - mActiveOutputVariables.clear(); + return mShader->getInterfaceBlocks(); } -const std::vector &FragmentShader::getOutputVariables() const +std::vector &Shader::getActiveAttributes() { - return mActiveOutputVariables; + return mShader->getActiveAttributes(); } -ShShaderOutput Shader::getCompilerOutputType(GLenum shader) +std::vector &Shader::getActiveOutputVariables() { - 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; - } - - size_t outputType = 0; - ShGetInfo(compiler, SH_OUTPUT_TYPE, &outputType); - - return static_cast(outputType); + return mShader->getActiveOutputVariables(); } } diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.h b/src/3rdparty/angle/src/libGLESv2/Shader.h index a40f415c1e..7ba3bd165c 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.h +++ b/src/3rdparty/angle/src/libGLESv2/Shader.h @@ -12,19 +12,20 @@ #ifndef LIBGLESV2_SHADER_H_ #define LIBGLESV2_SHADER_H_ -#include "angle_gl.h" + #include #include #include -#include "common/shadervars.h" +#include "angle_gl.h" +#include + #include "common/angleutils.h" #include "libGLESv2/angletypes.h" -#include "GLSLANG/ShaderLang.h" namespace rx { -class Renderer; +class ShaderImpl; } namespace gl @@ -34,13 +35,16 @@ class ResourceManager; 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) + 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() { @@ -50,16 +54,17 @@ struct PackedVarying : public sh::Varying class Shader { - friend class DynamicHLSL; - public: - Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle); + Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLuint handle); virtual ~Shader(); - virtual GLenum getType() const = 0; + 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; @@ -68,122 +73,44 @@ class Shader void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const; int getTranslatedSourceLength() const; void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const; - const std::vector &getUniforms() const; - const std::vector &getInterfaceBlocks() const; - std::vector &getVaryings(); - virtual void compile() = 0; - virtual void uncompile(); - bool isCompiled() const; - const std::string &getHLSL() const; + void compile(); + bool isCompiled() const { return mCompiled; } void addRef(); void release(); unsigned int getRefCount() const; bool isFlaggedForDeletion() const; void flagForDeletion(); - int getShaderVersion() const; - void resetVaryingsRegisterAssignment(); - - static void releaseCompiler(); - static ShShaderOutput getCompilerOutputType(GLenum shader); - unsigned int getUniformRegister(const std::string &uniformName) const; - unsigned int getInterfaceBlockRegister(const std::string &blockName) const; - - bool usesDepthRange() const { return mUsesDepthRange; } - bool usesPointSize() const { return mUsesPointSize; } - rx::D3DWorkaroundType getD3DWorkarounds() const; - - protected: - void parseVaryings(void *compiler); - void compileToHLSL(void *compiler); - - void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) const; - - static bool compareVarying(const PackedVarying &x, const PackedVarying &y); - - const rx::Renderer *const mRenderer; - - std::vector mVaryings; - - bool mUsesMultipleRenderTargets; - bool mUsesFragColor; - bool mUsesFragData; - bool mUsesFragCoord; - bool mUsesFrontFacing; - bool mUsesPointSize; - bool mUsesPointCoord; - bool mUsesDepthRange; - bool mUsesFragDepth; - int mShaderVersion; - bool mUsesDiscardRewriting; - bool mUsesNestedBreak; + 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; - static void *mFragmentCompiler; - static void *mVertexCompiler; + std::vector &getVaryings(); + std::vector &getUniforms(); + std::vector &getInterfaceBlocks(); + std::vector &getActiveAttributes(); + std::vector &getActiveOutputVariables(); private: DISALLOW_COPY_AND_ASSIGN(Shader); - void initializeCompiler(); + 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 - - std::string mSource; - std::string mHlsl; - std::string mInfoLog; - std::vector mActiveUniforms; - std::vector mActiveInterfaceBlocks; - std::map mUniformRegisterMap; - std::map mInterfaceBlockRegisterMap; + bool mCompiled; // Indicates if this shader has been successfully compiled ResourceManager *mResourceManager; }; -class VertexShader : public Shader -{ - friend class DynamicHLSL; - - public: - VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle); - - ~VertexShader(); - - virtual GLenum getType() const; - virtual void compile(); - virtual void uncompile(); - int getSemanticIndex(const std::string &attributeName); - - const std::vector &activeAttributes() const { return mActiveAttributes; } - - private: - DISALLOW_COPY_AND_ASSIGN(VertexShader); - - void parseAttributes(); - - std::vector mActiveAttributes; -}; - -class FragmentShader : public Shader -{ - public: - FragmentShader(ResourceManager *manager,const rx::Renderer *renderer, GLuint handle); - - ~FragmentShader(); - - virtual GLenum getType() const; - virtual void compile(); - virtual void uncompile(); - const std::vector &getOutputVariables() const; - - private: - DISALLOW_COPY_AND_ASSIGN(FragmentShader); - - std::vector mActiveOutputVariables; -}; } #endif // LIBGLESV2_SHADER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/State.cpp b/src/3rdparty/angle/src/libGLESv2/State.cpp index b552701727..3c03b90e56 100644 --- a/src/3rdparty/angle/src/libGLESv2/State.cpp +++ b/src/3rdparty/angle/src/libGLESv2/State.cpp @@ -1,4 +1,3 @@ -#include "precompiled.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 @@ -10,6 +9,7 @@ #include "libGLESv2/State.h" #include "libGLESv2/Context.h" +#include "libGLESv2/Caps.h" #include "libGLESv2/VertexArray.h" #include "libGLESv2/Query.h" #include "libGLESv2/Framebuffer.h" @@ -19,7 +19,17 @@ namespace gl { + State::State() +{ +} + +State::~State() +{ + reset(); +} + +void State::initialize(const Caps& caps, GLuint clientVersion) { mContext = NULL; @@ -66,7 +76,7 @@ State::State() mDepthStencil.stencilMask = -1; mDepthStencil.stencilWritemask = -1; mDepthStencil.stencilBackFunc = GL_ALWAYS; - mDepthStencil.stencilBackMask = - 1; + mDepthStencil.stencilBackMask = -1; mDepthStencil.stencilBackWritemask = -1; mDepthStencil.stencilFail = GL_KEEP; mDepthStencil.stencilPassDepthFail = GL_KEEP; @@ -98,18 +108,24 @@ State::State() mBlend.colorMaskBlue = true; mBlend.colorMaskAlpha = true; + mActiveSampler = 0; + const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++) { mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues); } - for (unsigned int textureUnit = 0; textureUnit < ArraySize(mSamplers); textureUnit++) + mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits); + mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits); + if (clientVersion >= 3) { - mSamplers[textureUnit].set(NULL); + // TODO: These could also be enabled via extension + mSamplerTextures[GL_TEXTURE_2D_ARRAY].resize(caps.maxCombinedTextureImageUnits); + mSamplerTextures[GL_TEXTURE_3D].resize(caps.maxCombinedTextureImageUnits); } - mActiveSampler = 0; + mSamplers.resize(caps.maxCombinedTextureImageUnits); mActiveQueries[GL_ANY_SAMPLES_PASSED].set(NULL); mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(NULL); @@ -122,15 +138,20 @@ State::State() mDrawFramebuffer = NULL; } -State::~State() +void State::reset() { - for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) + for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++) { - for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) + TextureBindingVector &textureVector = bindingVec->second; + for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++) { - mSamplerTexture[type][sampler].set(NULL); + textureVector[textureIdx].set(NULL); } } + for (size_t samplerIdx = 0; samplerIdx < mSamplers.size(); samplerIdx++) + { + mSamplers[samplerIdx].set(NULL); + } const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++) @@ -245,15 +266,8 @@ ClearParameters State::getClearParameters(GLbitfield mask) const { if (framebufferObject->getStencilbuffer() != NULL) { - rx::RenderTarget *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - ClearParameters nullClearParam = { 0 }; - return nullClearParam; - } - - if (GetStencilBits(depthStencil->getActualFormat()) > 0) + GLenum stencilActualFormat = framebufferObject->getStencilbuffer()->getActualFormat(); + if (GetInternalFormatInfo(stencilActualFormat).stencilBits > 0) { clearParams.clearStencil = true; } @@ -591,26 +605,26 @@ unsigned int State::getActiveSampler() const return mActiveSampler; } -void State::setSamplerTexture(TextureType type, Texture *texture) +void State::setSamplerTexture(GLenum type, Texture *texture) { - mSamplerTexture[type][mActiveSampler].set(texture); + mSamplerTextures[type][mActiveSampler].set(texture); } -Texture *State::getSamplerTexture(unsigned int sampler, TextureType type) const +Texture *State::getSamplerTexture(unsigned int sampler, GLenum type) const { - GLuint texid = mSamplerTexture[type][sampler].id(); + const BindingPointer& binding = mSamplerTextures.at(type)[sampler]; - if (texid == 0) // Special case: 0 refers to default textures held by Context + if (binding.id() == 0) // Special case: 0 refers to default textures held by Context { return NULL; } - return mSamplerTexture[type][sampler].get(); + return binding.get(); } -GLuint State::getSamplerTextureId(unsigned int sampler, TextureType type) const +GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const { - return mSamplerTexture[type][sampler].id(); + return mSamplerTextures.at(type)[sampler].id(); } void State::detachTexture(GLuint texture) @@ -624,13 +638,15 @@ void State::detachTexture(GLuint texture) // If a texture object is deleted, it is as if all texture units which are bound to that texture object are // rebound to texture object zero - for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) + for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++) { - for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) + TextureBindingVector &textureVector = bindingVec->second; + for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++) { - if (mSamplerTexture[type][sampler].id() == texture) + BindingPointer &binding = textureVector[textureIdx]; + if (binding.id() == texture) { - mSamplerTexture[type][sampler].set(NULL); + binding.set(NULL); } } } @@ -658,7 +674,7 @@ void State::setSamplerBinding(GLuint textureUnit, Sampler *sampler) GLuint State::getSamplerId(GLuint textureUnit) const { - ASSERT(textureUnit < ArraySize(mSamplers)); + ASSERT(textureUnit < mSamplers.size()); return mSamplers[textureUnit].id(); } @@ -673,11 +689,12 @@ void State::detachSampler(GLuint sampler) // 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 (unsigned int textureUnit = 0; textureUnit < ArraySize(mSamplers); textureUnit++) + for (size_t textureUnit = 0; textureUnit < mSamplers.size(); textureUnit++) { - if (mSamplers[textureUnit].id() == sampler) + BindingPointer &samplerBinding = mSamplers[textureUnit]; + if (samplerBinding.id() == sampler) { - mSamplers[textureUnit].set(NULL); + samplerBinding.set(NULL); } } } @@ -1315,20 +1332,20 @@ void State::getIntegerv(GLenum pname, GLint *params) } break; case GL_TEXTURE_BINDING_2D: - ASSERT(mActiveSampler < mContext->getMaximumCombinedTextureImageUnits()); - *params = mSamplerTexture[TEXTURE_2D][mActiveSampler].id(); + ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits); + *params = mSamplerTextures.at(GL_TEXTURE_2D)[mActiveSampler].id(); break; case GL_TEXTURE_BINDING_CUBE_MAP: - ASSERT(mActiveSampler < mContext->getMaximumCombinedTextureImageUnits()); - *params = mSamplerTexture[TEXTURE_CUBE][mActiveSampler].id(); + ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits); + *params = mSamplerTextures.at(GL_TEXTURE_CUBE_MAP)[mActiveSampler].id(); break; case GL_TEXTURE_BINDING_3D: - ASSERT(mActiveSampler < mContext->getMaximumCombinedTextureImageUnits()); - *params = mSamplerTexture[TEXTURE_3D][mActiveSampler].id(); + ASSERT(mActiveSampler getCaps().maxCombinedTextureImageUnits); + *params = mSamplerTextures.at(GL_TEXTURE_3D)[mActiveSampler].id(); break; case GL_TEXTURE_BINDING_2D_ARRAY: - ASSERT(mActiveSampler < mContext->getMaximumCombinedTextureImageUnits()); - *params = mSamplerTexture[TEXTURE_2D_ARRAY][mActiveSampler].id(); + ASSERT(mActiveSampler < mContext->getCaps().maxCombinedTextureImageUnits); + *params = mSamplerTextures.at(GL_TEXTURE_2D_ARRAY)[mActiveSampler].id(); break; case GL_UNIFORM_BUFFER_BINDING: *params = mGenericUniformBuffer.id(); @@ -1412,4 +1429,27 @@ bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) return true; } +bool State::hasMappedBuffer(GLenum target) const +{ + if (target == GL_ARRAY_BUFFER) + { + for (unsigned int attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; attribIndex++) + { + const gl::VertexAttribute &vertexAttrib = getVertexAttribState(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 index 09be0b335d..5f0433136c 100644 --- a/src/3rdparty/angle/src/libGLESv2/State.h +++ b/src/3rdparty/angle/src/libGLESv2/State.h @@ -24,6 +24,7 @@ namespace gl class Query; class VertexArray; class Context; +struct Caps; class State { @@ -31,6 +32,9 @@ class State State(); ~State(); + void initialize(const Caps& caps, GLuint clientVersion); + void reset(); + void setContext(Context *context) { mContext = context; } // State chunk getters @@ -126,9 +130,9 @@ class State // Texture binding & active texture unit manipulation void setActiveSampler(unsigned int active); unsigned int getActiveSampler() const; - void setSamplerTexture(TextureType type, Texture *texture); - Texture *getSamplerTexture(unsigned int sampler, TextureType type) const; - GLuint getSamplerTextureId(unsigned int sampler, TextureType type) 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(GLuint texture); // Sampler object binding manipulation @@ -238,6 +242,8 @@ class State 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); @@ -270,7 +276,6 @@ class State float mNearZ; float mFarZ; - unsigned int mActiveSampler; // Active texture unit selector - GL_TEXTURE0 BindingPointer mArrayBuffer; Framebuffer *mReadFramebuffer; Framebuffer *mDrawFramebuffer; @@ -281,8 +286,15 @@ class State VertexAttribCurrentValueData mVertexAttribCurrentValues[MAX_VERTEX_ATTRIBS]; // From glVertexAttrib VertexArray *mVertexArray; - BindingPointer mSamplerTexture[TEXTURE_TYPE_COUNT][IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; - BindingPointer mSamplers[IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; + // 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; diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp index b0c0ee51bd..3ec492de07 100644 --- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Texture.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -10,23 +9,47 @@ // functionality. [OpenGL ES 2.0.24] section 3.7 page 63. #include "libGLESv2/Texture.h" - #include "libGLESv2/main.h" -#include "common/mathutil.h" -#include "common/utilities.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 "libGLESv2/renderer/RenderTarget.h" -#include "libGLESv2/renderer/TextureImpl.h" + +#include "common/mathutil.h" +#include "common/utilities.h" namespace gl { -Texture::Texture(GLuint id, GLenum target) +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)); +} + +Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target) : RefCountObject(id), + mTexture(impl), mUsage(GL_NONE), mImmutable(false), mTarget(target) @@ -35,6 +58,7 @@ Texture::Texture(GLuint id, GLenum target) Texture::~Texture() { + SafeDelete(mTexture); } GLenum Texture::getTarget() const @@ -45,6 +69,7 @@ GLenum Texture::getTarget() const void Texture::setUsage(GLenum usage) { mUsage = usage; + getImplementation()->setUsage(usage); } void Texture::getSamplerStateWithNativeOffset(SamplerState *sampler) @@ -52,7 +77,7 @@ void Texture::getSamplerStateWithNativeOffset(SamplerState *sampler) *sampler = mSamplerState; // Offset the effective base level by the texture storage's top level - rx::TextureStorageInterface *texture = getNativeTexture(); + rx::TextureStorage *texture = getNativeTexture(); int topLevel = texture ? texture->getTopLevel() : 0; sampler->baseLevel = topLevel + mSamplerState.baseLevel; } @@ -89,9 +114,48 @@ GLenum Texture::getBaseLevelInternalFormat() const 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(); +} + +rx::TextureStorage *Texture::getNativeTexture() +{ + return getImplementation()->getNativeTexture(); +} + +void Texture::generateMipmaps() +{ + getImplementation()->generateMipmaps(); +} + +void Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +{ + getImplementation()->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source); +} + unsigned int Texture::getTextureSerial() { - rx::TextureStorageInterface *texture = getNativeTexture(); + rx::TextureStorage *texture = getNativeTexture(); return texture ? texture->getTextureSerial() : 0; } @@ -102,7 +166,7 @@ bool Texture::isImmutable() const int Texture::immutableLevelCount() { - return (mImmutable ? getNativeTexture()->getStorageInstance()->getLevelCount() : 0); + return (mImmutable ? getNativeTexture()->getLevelCount() : 0); } int Texture::mipLevels() const @@ -110,17 +174,19 @@ int Texture::mipLevels() const return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1; } -Texture2D::Texture2D(rx::Texture2DImpl *impl, GLuint id) - : Texture(id, GL_TEXTURE_2D), - mTexture(impl) +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() { - SafeDelete(mTexture); - if (mSurface) { mSurface->setBoundTexture(NULL); @@ -128,31 +194,10 @@ Texture2D::~Texture2D() } } -rx::TextureStorageInterface *Texture2D::getNativeTexture() -{ - return mTexture->getNativeTexture(); -} - -void Texture2D::setUsage(GLenum usage) -{ - mUsage = usage; - mTexture->setUsage(usage); -} - -bool Texture2D::hasDirtyImages() const -{ - return mTexture->hasDirtyImages(); -} - -void Texture2D::resetDirty() -{ - mTexture->resetDirty(); -} - GLsizei Texture2D::getWidth(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level)->getWidth(); + return mTexture->getImage(level, 0)->getWidth(); else return 0; } @@ -160,7 +205,7 @@ GLsizei Texture2D::getWidth(GLint level) const GLsizei Texture2D::getHeight(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level)->getHeight(); + return mTexture->getImage(level, 0)->getHeight(); else return 0; } @@ -168,7 +213,7 @@ GLsizei Texture2D::getHeight(GLint level) const GLenum Texture2D::getInternalFormat(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level)->getInternalFormat(); + return mTexture->getImage(level, 0)->getInternalFormat(); else return GL_NONE; } @@ -176,25 +221,16 @@ GLenum Texture2D::getInternalFormat(GLint level) const GLenum Texture2D::getActualFormat(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(level)->getActualFormat(); + return mTexture->getImage(level, 0)->getActualFormat(); else return GL_NONE; } -void Texture2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height) -{ - releaseTexImage(); - - mTexture->redefineImage(level, internalformat, width, height); -} - void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - GLenum sizedInternalFormat = IsSizedInternalFormat(internalFormat) ? internalFormat - : GetSizedInternalFormat(format, type); - redefineImage(level, sizedInternalFormat, width, height); + releaseTexImage(); - mTexture->setImage(level, width, height, internalFormat, format, type, unpack, pixels); + mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels); } void Texture2D::bindTexImage(egl::Surface *surface) @@ -220,129 +256,189 @@ void Texture2D::releaseTexImage() void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) { - // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly - redefineImage(level, format, width, height); + releaseTexImage(); - mTexture->setCompressedImage(level, format, width, height, imageSize, pixels); + mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, pixels); } void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->subImage(level, xoffset, yoffset, width, height, format, type, unpack, pixels); + mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels); } void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) { - mTexture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, pixels); + mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels); } void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - GLenum sizedInternalFormat = IsSizedInternalFormat(format) ? format - : GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); - redefineImage(level, sizedInternalFormat, width, height); - - mTexture->copyImage(level, format, x, y, width, height, source); -} + releaseTexImage(); -void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) -{ - mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source); + mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source); } void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { mImmutable = true; - mTexture->storage(levels, internalformat, width, height); + mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1); } // Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85. -bool Texture2D::isSamplerComplete(const SamplerState &samplerState) const +bool Texture2D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const { - return mTexture->isSamplerComplete(samplerState); + 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 IsFormatCompressed(getInternalFormat(level)); + return GetInternalFormatInfo(getInternalFormat(level)).compressed; } bool Texture2D::isDepth(GLint level) const { - return GetDepthBits(getInternalFormat(level)) > 0; + return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } void Texture2D::generateMipmaps() { - // 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)); - } + releaseTexImage(); mTexture->generateMipmaps(); } -const rx::Image *Texture2D::getBaseLevelImage() const +// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. +bool Texture2D::isMipmapComplete() const { - return mTexture->getImage(0); -} + int levelCount = mipLevels(); -unsigned int Texture2D::getRenderTargetSerial(GLint level) -{ - return mTexture->getRenderTargetSerial(level); -} + for (int level = 0; level < levelCount; level++) + { + if (!isLevelComplete(level)) + { + return false; + } + } -rx::RenderTarget *Texture2D::getRenderTarget(GLint level) -{ - return mTexture->getRenderTarget(level); + return true; } -rx::RenderTarget *Texture2D::getDepthSencil(GLint level) +bool Texture2D::isLevelComplete(int level) const { - return mTexture->getDepthSencil(level); -} + if (isImmutable()) + { + return true; + } -TextureCubeMap::TextureCubeMap(rx::TextureCubeImpl *impl, GLuint id) - : Texture(id, GL_TEXTURE_CUBE_MAP), - mTexture(impl) -{ -} + const rx::Image *baseImage = getBaseLevelImage(); -TextureCubeMap::~TextureCubeMap() -{ - SafeDelete(mTexture); -} + GLsizei width = baseImage->getWidth(); + GLsizei height = baseImage->getHeight(); -rx::TextureStorageInterface *TextureCubeMap::getNativeTexture() -{ - return mTexture->getNativeTexture(); -} + if (width <= 0 || height <= 0) + { + return false; + } -void TextureCubeMap::setUsage(GLenum usage) -{ - mUsage = usage; - mTexture->setUsage(usage); + // 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; } -bool TextureCubeMap::hasDirtyImages() const +TextureCubeMap::TextureCubeMap(rx::TextureImpl *impl, GLuint id) + : Texture(impl, id, GL_TEXTURE_CUBE_MAP) { - return mTexture->hasDirtyImages(); } -void TextureCubeMap::resetDirty() +TextureCubeMap::~TextureCubeMap() { - mTexture->resetDirty(); } GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(target, level)->getWidth(); + return mTexture->getImage(level, targetToLayerIndex(target))->getWidth(); else return 0; } @@ -350,7 +446,7 @@ GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(target, level)->getHeight(); + return mTexture->getImage(level, targetToLayerIndex(target))->getHeight(); else return 0; } @@ -358,7 +454,7 @@ GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(target, level)->getInternalFormat(); + return mTexture->getImage(level, targetToLayerIndex(target))->getInternalFormat(); else return GL_NONE; } @@ -366,76 +462,91 @@ GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mTexture->getImage(target, level)->getActualFormat(); + return mTexture->getImage(level, targetToLayerIndex(target))->getActualFormat(); else return GL_NONE; } void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(0, level, width, height, internalFormat, format, type, unpack, pixels); + mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, width, height, 1, internalFormat, format, type, unpack, pixels); } void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(1, level, width, height, internalFormat, format, type, unpack, pixels); + mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, width, height, 1, internalFormat, format, type, unpack, pixels); } void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(2, level, width, height, internalFormat, format, type, unpack, pixels); + mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, width, height, 1, internalFormat, format, type, unpack, pixels); } void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(3, level, width, height, internalFormat, format, type, unpack, pixels); + mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, width, height, 1, internalFormat, format, type, unpack, pixels); } void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(4, level, width, height, internalFormat, format, type, unpack, pixels); + mTexture->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, width, height, 1, internalFormat, format, type, unpack, pixels); } void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(5, level, width, height, internalFormat, format, type, unpack, pixels); + mTexture->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, width, height, 1, internalFormat, format, type, unpack, pixels); } void TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) { - mTexture->setCompressedImage(target, level, format, width, height, imageSize, pixels); + mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, pixels); } void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->subImage(target, level, xoffset, yoffset, width, height, format, type, unpack, pixels); + mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels); } void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) { - mTexture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, pixels); -} - -// Tests for cube map sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 86. -bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState) const -{ - return mTexture->isSamplerComplete(samplerState); + mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels); } // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. bool TextureCubeMap::isCubeComplete() const { - return mTexture->isCubeComplete(); + 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 IsFormatCompressed(getInternalFormat(target, level)); + return GetInternalFormatInfo(getInternalFormat(target, level)).compressed; } bool TextureCubeMap::isDepth(GLenum target, GLint level) const { - return GetDepthBits(getInternalFormat(target, level)) > 0; + return GetInternalFormatInfo(getInternalFormat(target, level)).depthBits > 0; } void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) @@ -443,214 +554,307 @@ void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint mTexture->copyImage(target, level, format, x, y, width, height, source); } -void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) -{ - mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source); -} - void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size) { mImmutable = true; - mTexture->storage(levels, internalformat, size); + mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1); } -void TextureCubeMap::generateMipmaps() +// Tests for texture sampling completeness +bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const { - mTexture->generateMipmaps(); -} + int size = getBaseLevelWidth(); -const rx::Image *TextureCubeMap::getBaseLevelImage() const -{ - // Note: if we are not cube-complete, there is no single base level image that can describe all - // cube faces, so this method is only well-defined for a cube-complete base level. - return mTexture->getImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0); -} + bool mipmapping = IsMipmapFiltered(samplerState); -unsigned int TextureCubeMap::getRenderTargetSerial(GLenum target, GLint level) -{ - return mTexture->getRenderTargetSerial(target, level); -} + if (!textureCaps.get(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)).filterable && !IsPointSampled(samplerState)) + { + return false; + } -rx::RenderTarget *TextureCubeMap::getRenderTarget(GLenum target, GLint level) -{ - return mTexture->getRenderTarget(target, level); -} + if (!gl::isPow2(size) && !extensions.textureNPOT) + { + if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping) + { + return false; + } + } -rx::RenderTarget *TextureCubeMap::getDepthStencil(GLenum target, GLint level) -{ - return mTexture->getDepthStencil(target, level); + if (!mipmapping) + { + if (!isCubeComplete()) + { + return false; + } + } + else + { + if (!isMipmapComplete()) // Also tests for isCubeComplete() + { + return false; + } + } + + return true; } -Texture3D::Texture3D(rx::Texture3DImpl *impl, GLuint id) - : Texture(id, GL_TEXTURE_3D), - mTexture(impl) +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; } -Texture3D::~Texture3D() +GLenum TextureCubeMap::layerIndexToTarget(GLint layer) { - SafeDelete(mTexture); + 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; } -rx::TextureStorageInterface *Texture3D::getNativeTexture() +bool TextureCubeMap::isMipmapComplete() const { - return mTexture->getNativeTexture(); + 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; } -void Texture3D::setUsage(GLenum usage) +bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const { - mUsage = usage; - mTexture->setUsage(usage); + 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; } -bool Texture3D::hasDirtyImages() const + +Texture3D::Texture3D(rx::TextureImpl *impl, GLuint id) + : Texture(impl, id, GL_TEXTURE_3D) { - return mTexture->hasDirtyImages(); } -void Texture3D::resetDirty() +Texture3D::~Texture3D() { - mTexture->resetDirty(); } GLsizei Texture3D::getWidth(GLint level) const { - return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level)->getWidth() : 0; + 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)->getHeight() : 0; + 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)->getDepth() : 0; + 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)->getInternalFormat() : GL_NONE; + 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)->getActualFormat() : GL_NONE; + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getActualFormat() : GL_NONE; } bool Texture3D::isCompressed(GLint level) const { - return IsFormatCompressed(getInternalFormat(level)); + return GetInternalFormatInfo(getInternalFormat(level)).compressed; } bool Texture3D::isDepth(GLint level) const { - return GetDepthBits(getInternalFormat(level)) > 0; + return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } void Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(level, width, height, depth, internalFormat, format, type, unpack, pixels); + mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels); } void Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) { - mTexture->setCompressedImage(level, format, width, height, depth, imageSize, pixels); + mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, pixels); } void 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) { - mTexture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); + mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); } void Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) { - mTexture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels); + mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels); } void Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { mImmutable = true; - mTexture->storage(levels, internalformat, width, height, depth); + mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth); } -void Texture3D::generateMipmaps() +bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const { - mTexture->generateMipmaps(); -} + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getBaseLevelDepth(); -const rx::Image *Texture3D::getBaseLevelImage() const -{ - return mTexture->getImage(0); -} + if (width <= 0 || height <= 0 || depth <= 0) + { + return false; + } -void Texture3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) -{ - mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source); -} + if (!textureCaps.get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState)) + { + return false; + } -bool Texture3D::isSamplerComplete(const SamplerState &samplerState) const -{ - return mTexture->isSamplerComplete(samplerState); + if (IsMipmapFiltered(samplerState) && !isMipmapComplete()) + { + return false; + } + + return true; } bool Texture3D::isMipmapComplete() const { - return mTexture->isMipmapComplete(); -} + int levelCount = mipLevels(); -unsigned int Texture3D::getRenderTargetSerial(GLint level, GLint layer) -{ - return mTexture->getRenderTargetSerial(level, layer); -} + for (int level = 0; level < levelCount; level++) + { + if (!isLevelComplete(level)) + { + return false; + } + } -rx::RenderTarget *Texture3D::getRenderTarget(GLint level) -{ - return mTexture->getRenderTarget(level); + return true; } -rx::RenderTarget *Texture3D::getRenderTarget(GLint level, GLint layer) +bool Texture3D::isLevelComplete(int level) const { - return mTexture->getRenderTarget(level, layer); -} + ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL); -rx::RenderTarget *Texture3D::getDepthStencil(GLint level, GLint layer) -{ - return mTexture->getDepthStencil(level, layer); -} + if (isImmutable()) + { + return true; + } -Texture2DArray::Texture2DArray(rx::Texture2DArrayImpl *impl, GLuint id) - : Texture(id, GL_TEXTURE_2D_ARRAY), - mTexture(impl) -{ -} + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getBaseLevelDepth(); -Texture2DArray::~Texture2DArray() -{ - SafeDelete(mTexture); -} + if (width <= 0 || height <= 0 || depth <= 0) + { + return false; + } -rx::TextureStorageInterface *Texture2DArray::getNativeTexture() -{ - return mTexture->getNativeTexture(); -} + if (level == 0) + { + return true; + } -void Texture2DArray::setUsage(GLenum usage) -{ - mUsage = usage; - mTexture->setUsage(usage); + 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; } -bool Texture2DArray::hasDirtyImages() const +Texture2DArray::Texture2DArray(rx::TextureImpl *impl, GLuint id) + : Texture(impl, id, GL_TEXTURE_2D_ARRAY) { - return mTexture->hasDirtyImages(); } -void Texture2DArray::resetDirty() +Texture2DArray::~Texture2DArray() { - mTexture->resetDirty(); } GLsizei Texture2DArray::getWidth(GLint level) const @@ -680,79 +884,124 @@ GLenum Texture2DArray::getActualFormat(GLint level) const bool Texture2DArray::isCompressed(GLint level) const { - return IsFormatCompressed(getInternalFormat(level)); + return GetInternalFormatInfo(getInternalFormat(level)).compressed; } bool Texture2DArray::isDepth(GLint level) const { - return GetDepthBits(getInternalFormat(level)) > 0; + return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } void Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - mTexture->setImage(level, width, height, depth, internalFormat, format, type, unpack, pixels); + mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels); } void Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) { - mTexture->setCompressedImage(level, format, width, height, depth, imageSize, pixels); + mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, pixels); } void 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) { - mTexture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); + mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); } void Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) { - mTexture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels); + mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels); } void Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { mImmutable = true; - mTexture->storage(levels, internalformat, width, height, depth); + mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth); } -void Texture2DArray::generateMipmaps() +bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const { - mTexture->generateMipmaps(); -} + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getLayers(0); -const rx::Image *Texture2DArray::getBaseLevelImage() const -{ - return (mTexture->getLayerCount(0) > 0 ? mTexture->getImage(0, 0) : NULL); -} + if (width <= 0 || height <= 0 || depth <= 0) + { + return false; + } -void Texture2DArray::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) -{ - mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source); -} + if (!textureCaps.get(getBaseLevelInternalFormat()).filterable && !IsPointSampled(samplerState)) + { + return false; + } -bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState) const -{ - return mTexture->isSamplerComplete(samplerState); + if (IsMipmapFiltered(samplerState) && !isMipmapComplete()) + { + return false; + } + + return true; } bool Texture2DArray::isMipmapComplete() const { - return mTexture->isMipmapComplete(); -} + int levelCount = mipLevels(); -unsigned int Texture2DArray::getRenderTargetSerial(GLint level, GLint layer) -{ - return mTexture->getRenderTargetSerial(level, layer); -} + for (int level = 1; level < levelCount; level++) + { + if (!isLevelComplete(level)) + { + return false; + } + } -rx::RenderTarget *Texture2DArray::getRenderTarget(GLint level, GLint layer) -{ - return mTexture->getRenderTarget(level, layer); + return true; } -rx::RenderTarget *Texture2DArray::getDepthStencil(GLint level, GLint layer) +bool Texture2DArray::isLevelComplete(int level) const { - return mTexture->getDepthStencil(level, layer); + 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 index 29f952f9f6..ca5686fde3 100644 --- a/src/3rdparty/angle/src/libGLESv2/Texture.h +++ b/src/3rdparty/angle/src/libGLESv2/Texture.h @@ -11,14 +11,16 @@ #ifndef LIBGLESV2_TEXTURE_H_ #define LIBGLESV2_TEXTURE_H_ -#include - -#include "angle_gl.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 { @@ -27,12 +29,7 @@ class Surface; namespace rx { -class Texture2DImpl; -class TextureCubeImpl; -class Texture3DImpl; -class Texture2DArrayImpl; class TextureStorageInterface; -class RenderTarget; class Image; } @@ -40,11 +37,14 @@ namespace gl { class Framebuffer; class FramebufferAttachment; +struct ImageIndex; + +bool IsMipmapFiltered(const gl::SamplerState &samplerState); class Texture : public RefCountObject { public: - Texture(GLuint id, GLenum target); + Texture(rx::TextureImpl *impl, GLuint id, GLenum target); virtual ~Texture(); @@ -54,7 +54,7 @@ class Texture : public RefCountObject SamplerState &getSamplerState() { return mSamplerState; } void getSamplerStateWithNativeOffset(SamplerState *sampler); - virtual void setUsage(GLenum usage); + void setUsage(GLenum usage); GLenum getUsage() const; GLint getBaseLevelWidth() const; @@ -62,25 +62,33 @@ class Texture : public RefCountObject GLint getBaseLevelDepth() const; GLenum getBaseLevelInternalFormat() const; - virtual bool isSamplerComplete(const SamplerState &samplerState) const = 0; + 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 rx::TextureStorageInterface *getNativeTexture() = 0; + virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const = 0; - virtual void generateMipmaps() = 0; - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) = 0; + rx::TextureStorage *getNativeTexture(); + + virtual void generateMipmaps(); + virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - virtual bool hasDirtyImages() const = 0; - virtual void resetDirty() = 0; unsigned int getTextureSerial(); bool isImmutable() const; int 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; + rx::TextureImpl *mTexture; + SamplerState mSamplerState; GLenum mUsage; @@ -88,23 +96,18 @@ class Texture : public RefCountObject GLenum mTarget; + const rx::Image *getBaseLevelImage() const; + private: DISALLOW_COPY_AND_ASSIGN(Texture); - - virtual const rx::Image *getBaseLevelImage() const = 0; }; class Texture2D : public Texture { public: - Texture2D(rx::Texture2DImpl *impl, GLuint id); - - ~Texture2D(); + Texture2D(rx::TextureImpl *impl, GLuint id); - virtual rx::TextureStorageInterface *getNativeTexture(); - virtual void setUsage(GLenum usage); - virtual bool hasDirtyImages() const; - virtual void resetDirty(); + virtual ~Texture2D(); GLsizei getWidth(GLint level) const; GLsizei getHeight(GLint level) const; @@ -118,44 +121,29 @@ class Texture2D : public Texture void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); - virtual bool isSamplerComplete(const SamplerState &samplerState) const; + 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 void generateMipmaps(); - unsigned int getRenderTargetSerial(GLint level); - - protected: - friend class Texture2DAttachment; - rx::RenderTarget *getRenderTarget(GLint level); - rx::RenderTarget *getDepthSencil(GLint level); - private: DISALLOW_COPY_AND_ASSIGN(Texture2D); - virtual const rx::Image *getBaseLevelImage() const; + bool isMipmapComplete() const; + bool isLevelComplete(int level) const; - void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height); - - rx::Texture2DImpl *mTexture; egl::Surface *mSurface; }; class TextureCubeMap : public Texture { public: - TextureCubeMap(rx::TextureCubeImpl *impl, GLuint id); - - ~TextureCubeMap(); + TextureCubeMap(rx::TextureImpl *impl, GLuint id); - virtual rx::TextureStorageInterface *getNativeTexture(); - virtual void setUsage(GLenum usage); - virtual bool hasDirtyImages() const; - virtual void resetDirty(); + virtual ~TextureCubeMap(); GLsizei getWidth(GLenum target, GLint level) const; GLsizei getHeight(GLenum target, GLint level) const; @@ -176,40 +164,28 @@ class TextureCubeMap : public Texture void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); void storage(GLsizei levels, GLenum internalformat, GLsizei size); - virtual bool isSamplerComplete(const SamplerState &samplerState) const; - bool isCubeComplete() const; - - virtual void generateMipmaps(); + virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; - unsigned int getRenderTargetSerial(GLenum target, GLint level); + bool isCubeComplete() const; - protected: - friend class TextureCubeMapAttachment; - rx::RenderTarget *getRenderTarget(GLenum target, GLint level); - rx::RenderTarget *getDepthStencil(GLenum target, GLint level); + static int targetToLayerIndex(GLenum target); + static GLenum layerIndexToTarget(GLint layer); private: DISALLOW_COPY_AND_ASSIGN(TextureCubeMap); - virtual const rx::Image *getBaseLevelImage() const; - - rx::TextureCubeImpl *mTexture; + bool isMipmapComplete() const; + bool isFaceLevelComplete(int faceIndex, int level) const; }; class Texture3D : public Texture { public: - Texture3D(rx::Texture3DImpl *impl, GLuint id); - - ~Texture3D(); + Texture3D(rx::TextureImpl *impl, GLuint id); - virtual rx::TextureStorageInterface *getNativeTexture(); - virtual void setUsage(GLenum usage); - virtual bool hasDirtyImages() const; - virtual void resetDirty(); + virtual ~Texture3D(); GLsizei getWidth(GLint level) const; GLsizei getHeight(GLint level) const; @@ -225,39 +201,21 @@ class Texture3D : public Texture void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - virtual void generateMipmaps(); - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - - virtual bool isSamplerComplete(const SamplerState &samplerState) const; - virtual bool isMipmapComplete() const; - - unsigned int getRenderTargetSerial(GLint level, GLint layer); - - protected: - friend class Texture3DAttachment; - rx::RenderTarget *getRenderTarget(GLint level); - rx::RenderTarget *getRenderTarget(GLint level, GLint layer); - rx::RenderTarget *getDepthStencil(GLint level, GLint layer); + virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; private: DISALLOW_COPY_AND_ASSIGN(Texture3D); - virtual const rx::Image *getBaseLevelImage() const; - - rx::Texture3DImpl *mTexture; + bool isMipmapComplete() const; + bool isLevelComplete(int level) const; }; class Texture2DArray : public Texture { public: - Texture2DArray(rx::Texture2DArrayImpl *impl, GLuint id); + Texture2DArray(rx::TextureImpl *impl, GLuint id); - ~Texture2DArray(); - - virtual rx::TextureStorageInterface *getNativeTexture(); - virtual void setUsage(GLenum usage); - virtual bool hasDirtyImages() const; - virtual void resetDirty(); + virtual ~Texture2DArray(); GLsizei getWidth(GLint level) const; GLsizei getHeight(GLint level) const; @@ -273,25 +231,13 @@ class Texture2DArray : public Texture void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - virtual void generateMipmaps(); - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source); - - virtual bool isSamplerComplete(const SamplerState &samplerState) const; - virtual bool isMipmapComplete() const; - - unsigned int getRenderTargetSerial(GLint level, GLint layer); - - protected: - friend class Texture2DArrayAttachment; - rx::RenderTarget *getRenderTarget(GLint level, GLint layer); - rx::RenderTarget *getDepthStencil(GLint level, GLint layer); + virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const; private: DISALLOW_COPY_AND_ASSIGN(Texture2DArray); - virtual const rx::Image *getBaseLevelImage() const; - - rx::Texture2DArrayImpl *mTexture; + bool isMipmapComplete() const; + bool isLevelComplete(int level) const; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp b/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp index 79ce08405d..bfa7072326 100644 --- a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp +++ b/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp @@ -5,20 +5,24 @@ // #include "libGLESv2/TransformFeedback.h" +#include "libGLESv2/renderer/TransformFeedbackImpl.h" namespace gl { -TransformFeedback::TransformFeedback(GLuint id) +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) @@ -26,6 +30,7 @@ void TransformFeedback::start(GLenum primitiveMode) mStarted = GL_TRUE; mPrimitiveMode = primitiveMode; mPaused = GL_FALSE; + mTransformFeedback->begin(primitiveMode); } void TransformFeedback::stop() @@ -33,6 +38,7 @@ void TransformFeedback::stop() mStarted = GL_FALSE; mPrimitiveMode = GL_NONE; mPaused = GL_FALSE; + mTransformFeedback->end(); } GLboolean TransformFeedback::isStarted() const @@ -48,11 +54,13 @@ GLenum TransformFeedback::getDrawMode() const void TransformFeedback::pause() { mPaused = GL_TRUE; + mTransformFeedback->pause(); } void TransformFeedback::resume() { mPaused = GL_FALSE; + mTransformFeedback->resume(); } GLboolean TransformFeedback::isPaused() const diff --git a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h b/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h index d6f4522e2a..885a4fe172 100644 --- a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h +++ b/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h @@ -12,13 +12,18 @@ #include "angle_gl.h" +namespace rx +{ +class TransformFeedbackImpl; +} + namespace gl { class TransformFeedback : public RefCountObject { public: - explicit TransformFeedback(GLuint id); + TransformFeedback(rx::TransformFeedbackImpl* impl, GLuint id); virtual ~TransformFeedback(); void start(GLenum primitiveMode); @@ -34,6 +39,8 @@ class TransformFeedback : public RefCountObject private: DISALLOW_COPY_AND_ASSIGN(TransformFeedback); + rx::TransformFeedbackImpl* mTransformFeedback; + GLboolean mStarted; GLenum mPrimitiveMode; GLboolean mPaused; diff --git a/src/3rdparty/angle/src/libGLESv2/Uniform.cpp b/src/3rdparty/angle/src/libGLESv2/Uniform.cpp index cddc7ec7d0..bd0cd2eeec 100644 --- a/src/3rdparty/angle/src/libGLESv2/Uniform.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Uniform.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2010-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be diff --git a/src/3rdparty/angle/src/libGLESv2/Uniform.h b/src/3rdparty/angle/src/libGLESv2/Uniform.h index 24f834f3c6..633d70bb19 100644 --- a/src/3rdparty/angle/src/libGLESv2/Uniform.h +++ b/src/3rdparty/angle/src/libGLESv2/Uniform.h @@ -7,15 +7,15 @@ #ifndef LIBGLESV2_UNIFORM_H_ #define LIBGLESV2_UNIFORM_H_ -#include -#include +#include "common/debug.h" +#include "common/blocklayout.h" + +#include "libGLESv2/angletypes.h" #include "angle_gl.h" -#include "common/debug.h" -#include "angletypes.h" -#include "common/shadervars.h" -#include "common/blocklayout.h" +#include +#include namespace gl { diff --git a/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp b/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp index 120064a532..f8ca661062 100644 --- a/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp +++ b/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be diff --git a/src/3rdparty/angle/src/libGLESv2/VertexArray.h b/src/3rdparty/angle/src/libGLESv2/VertexArray.h index accd98731a..993ba042cf 100644 --- a/src/3rdparty/angle/src/libGLESv2/VertexArray.h +++ b/src/3rdparty/angle/src/libGLESv2/VertexArray.h @@ -17,6 +17,8 @@ #include "libGLESv2/constants.h" #include "libGLESv2/VertexAttribute.h" +#include + namespace rx { class Renderer; diff --git a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp b/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp index 7d011ef758..1096856b8a 100644 --- a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp +++ b/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright 2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp index bc929c7d0c..bb6425df64 100644 --- a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp +++ b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.h b/src/3rdparty/angle/src/libGLESv2/angletypes.h index 79ad810e9e..642a6ec266 100644 --- a/src/3rdparty/angle/src/libGLESv2/angletypes.h +++ b/src/3rdparty/angle/src/libGLESv2/angletypes.h @@ -11,6 +11,7 @@ #include "libGLESv2/constants.h" #include "common/RefCountObject.h" +#include namespace gl { @@ -19,17 +20,6 @@ class ProgramBinary; struct VertexAttribute; struct VertexAttribCurrentValueData; -enum TextureType -{ - TEXTURE_2D, - TEXTURE_CUBE, - TEXTURE_3D, - TEXTURE_2D_ARRAY, - - TEXTURE_TYPE_COUNT, - TEXTURE_UNKNOWN -}; - enum SamplerType { SAMPLER_PIXEL, diff --git a/src/3rdparty/angle/src/libGLESv2/constants.h b/src/3rdparty/angle/src/libGLESv2/constants.h index c87f92d497..69c4823fb2 100644 --- a/src/3rdparty/angle/src/libGLESv2/constants.h +++ b/src/3rdparty/angle/src/libGLESv2/constants.h @@ -15,12 +15,8 @@ namespace gl enum { MAX_VERTEX_ATTRIBS = 16, - MAX_TEXTURE_IMAGE_UNITS = 16, // Implementation upper limits, real maximums depend on the hardware - IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS = 16, - IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS = MAX_TEXTURE_IMAGE_UNITS + IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS, - IMPLEMENTATION_MAX_VARYING_VECTORS = 32, IMPLEMENTATION_MAX_DRAW_BUFFERS = 8, IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS = IMPLEMENTATION_MAX_DRAW_BUFFERS + 2, // 2 extra for depth and/or stencil buffers diff --git a/src/3rdparty/angle/src/libGLESv2/formatutils.cpp b/src/3rdparty/angle/src/libGLESv2/formatutils.cpp index 8cc2e19a83..8674d5337f 100644 --- a/src/3rdparty/angle/src/libGLESv2/formatutils.cpp +++ b/src/3rdparty/angle/src/libGLESv2/formatutils.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -22,24 +21,23 @@ namespace gl // can decide the true, sized, internal format. The ES2FormatMap determines the internal format for all valid // format and type combinations. -struct FormatTypeInfo +FormatType::FormatType() + : internalFormat(GL_NONE), + colorWriteFunction(NULL) { - GLenum mInternalFormat; - ColorWriteFunction mColorWriteFunction; - - FormatTypeInfo(GLenum internalFormat, ColorWriteFunction writeFunc) - : mInternalFormat(internalFormat), mColorWriteFunction(writeFunc) - { } -}; +} typedef std::pair FormatTypePair; -typedef std::pair FormatPair; -typedef std::map FormatMap; +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) { - map->insert(FormatPair(FormatTypePair(format, type), FormatTypeInfo(internalFormat, writeFunc))); + FormatType info; + info.internalFormat = internalFormat; + info.colorWriteFunction = writeFunc; + map->insert(FormatPair(FormatTypePair(format, type), info)); } FormatMap BuildFormatMap() @@ -145,278 +143,59 @@ FormatMap BuildFormatMap() return map; } -static const FormatMap &GetFormatMap() +Type::Type() + : bytes(0), + specialInterpretation(false) { - static const FormatMap formatMap = BuildFormatMap(); - return formatMap; } -struct FormatInfo -{ - GLenum mInternalformat; - GLenum mFormat; - GLenum mType; - - FormatInfo(GLenum internalformat, GLenum format, GLenum type) - : mInternalformat(internalformat), mFormat(format), mType(type) { } - - bool operator<(const FormatInfo& other) const - { - return memcmp(this, &other, sizeof(FormatInfo)) < 0; - } -}; - -// ES3 has a specific set of permutations of internal formats, formats and types which are acceptable. -typedef std::set ES3FormatSet; +// Map of sizes of input types +typedef std::pair TypeInfoPair; +typedef std::map TypeInfoMap; -ES3FormatSet BuildES3FormatSet() +static inline void InsertTypeInfo(TypeInfoMap *map, GLenum type, GLuint bytes, bool specialInterpretation) { - ES3FormatSet set; - - // Format combinations from ES 3.0.1 spec, table 3.2 - - // | Internal format | Format | Type | - // | | | | - set.insert(FormatInfo(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_SRGB8_ALPHA8, GL_RGBA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGBA8_SNORM, GL_RGBA, GL_BYTE )); - set.insert(FormatInfo(GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 )); - set.insert(FormatInfo(GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV )); - set.insert(FormatInfo(GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV )); - set.insert(FormatInfo(GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 )); - set.insert(FormatInfo(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_RGBA16F, GL_RGBA, GL_HALF_FLOAT_OES )); - set.insert(FormatInfo(GL_RGBA32F, GL_RGBA, GL_FLOAT )); - set.insert(FormatInfo(GL_RGBA16F, GL_RGBA, GL_FLOAT )); - set.insert(FormatInfo(GL_RGBA8UI, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGBA8I, GL_RGBA_INTEGER, GL_BYTE )); - set.insert(FormatInfo(GL_RGBA16UI, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT )); - set.insert(FormatInfo(GL_RGBA16I, GL_RGBA_INTEGER, GL_SHORT )); - set.insert(FormatInfo(GL_RGBA32UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT )); - set.insert(FormatInfo(GL_RGBA32I, GL_RGBA_INTEGER, GL_INT )); - set.insert(FormatInfo(GL_RGB10_A2UI, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV )); - set.insert(FormatInfo(GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGB565, GL_RGB, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_SRGB8, GL_RGB, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGB8_SNORM, GL_RGB, GL_BYTE )); - set.insert(FormatInfo(GL_RGB565, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 )); - set.insert(FormatInfo(GL_R11F_G11F_B10F, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV )); - set.insert(FormatInfo(GL_RGB9_E5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV )); - set.insert(FormatInfo(GL_RGB16F, GL_RGB, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_RGB16F, GL_RGB, GL_HALF_FLOAT_OES )); - set.insert(FormatInfo(GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_R11F_G11F_B10F, GL_RGB, GL_HALF_FLOAT_OES )); - set.insert(FormatInfo(GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_RGB9_E5, GL_RGB, GL_HALF_FLOAT_OES )); - set.insert(FormatInfo(GL_RGB32F, GL_RGB, GL_FLOAT )); - set.insert(FormatInfo(GL_RGB16F, GL_RGB, GL_FLOAT )); - set.insert(FormatInfo(GL_R11F_G11F_B10F, GL_RGB, GL_FLOAT )); - set.insert(FormatInfo(GL_RGB9_E5, GL_RGB, GL_FLOAT )); - set.insert(FormatInfo(GL_RGB8UI, GL_RGB_INTEGER, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGB8I, GL_RGB_INTEGER, GL_BYTE )); - set.insert(FormatInfo(GL_RGB16UI, GL_RGB_INTEGER, GL_UNSIGNED_SHORT )); - set.insert(FormatInfo(GL_RGB16I, GL_RGB_INTEGER, GL_SHORT )); - set.insert(FormatInfo(GL_RGB32UI, GL_RGB_INTEGER, GL_UNSIGNED_INT )); - set.insert(FormatInfo(GL_RGB32I, GL_RGB_INTEGER, GL_INT )); - set.insert(FormatInfo(GL_RG8, GL_RG, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RG8_SNORM, GL_RG, GL_BYTE )); - set.insert(FormatInfo(GL_RG16F, GL_RG, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_RG16F, GL_RG, GL_HALF_FLOAT_OES )); - set.insert(FormatInfo(GL_RG32F, GL_RG, GL_FLOAT )); - set.insert(FormatInfo(GL_RG16F, GL_RG, GL_FLOAT )); - set.insert(FormatInfo(GL_RG8UI, GL_RG_INTEGER, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RG8I, GL_RG_INTEGER, GL_BYTE )); - set.insert(FormatInfo(GL_RG16UI, GL_RG_INTEGER, GL_UNSIGNED_SHORT )); - set.insert(FormatInfo(GL_RG16I, GL_RG_INTEGER, GL_SHORT )); - set.insert(FormatInfo(GL_RG32UI, GL_RG_INTEGER, GL_UNSIGNED_INT )); - set.insert(FormatInfo(GL_RG32I, GL_RG_INTEGER, GL_INT )); - set.insert(FormatInfo(GL_R8, GL_RED, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_R8_SNORM, GL_RED, GL_BYTE )); - set.insert(FormatInfo(GL_R16F, GL_RED, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_R16F, GL_RED, GL_HALF_FLOAT_OES )); - set.insert(FormatInfo(GL_R32F, GL_RED, GL_FLOAT )); - set.insert(FormatInfo(GL_R16F, GL_RED, GL_FLOAT )); - set.insert(FormatInfo(GL_R8UI, GL_RED_INTEGER, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_R8I, GL_RED_INTEGER, GL_BYTE )); - set.insert(FormatInfo(GL_R16UI, GL_RED_INTEGER, GL_UNSIGNED_SHORT )); - set.insert(FormatInfo(GL_R16I, GL_RED_INTEGER, GL_SHORT )); - set.insert(FormatInfo(GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT )); - set.insert(FormatInfo(GL_R32I, GL_RED_INTEGER, GL_INT )); - - // Unsized formats - set.insert(FormatInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 )); - set.insert(FormatInfo(GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 )); - set.insert(FormatInfo(GL_RGB, GL_RGB, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5 )); - set.insert(FormatInfo(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_SRGB_ALPHA_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_SRGB_EXT, GL_SRGB_EXT, GL_UNSIGNED_BYTE )); + Type info; + info.bytes = bytes; + info.specialInterpretation = specialInterpretation; - // Depth stencil formats - set.insert(FormatInfo(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT )); - set.insert(FormatInfo(GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT )); - set.insert(FormatInfo(GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT )); - set.insert(FormatInfo(GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT, GL_FLOAT )); - set.insert(FormatInfo(GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8 )); - set.insert(FormatInfo(GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV)); - - // From GL_EXT_sRGB - set.insert(FormatInfo(GL_SRGB8_ALPHA8_EXT, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_SRGB8, GL_SRGB_EXT, GL_UNSIGNED_BYTE )); - - // From GL_OES_texture_float - set.insert(FormatInfo(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_FLOAT )); - set.insert(FormatInfo(GL_LUMINANCE, GL_LUMINANCE, GL_FLOAT )); - set.insert(FormatInfo(GL_ALPHA, GL_ALPHA, GL_FLOAT )); - - // From GL_OES_texture_half_float - set.insert(FormatInfo(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES )); - set.insert(FormatInfo(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_LUMINANCE, GL_LUMINANCE, GL_HALF_FLOAT_OES )); - set.insert(FormatInfo(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_ALPHA, GL_ALPHA, GL_HALF_FLOAT_OES )); - - // From GL_EXT_texture_format_BGRA8888 - set.insert(FormatInfo(GL_BGRA_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE )); - - // From GL_EXT_texture_storage - // | Internal format | Format | Type | - // | | | | - set.insert(FormatInfo(GL_ALPHA8_EXT, GL_ALPHA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_LUMINANCE8_EXT, GL_LUMINANCE, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_LUMINANCE8_ALPHA8_EXT, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_ALPHA32F_EXT, GL_ALPHA, GL_FLOAT )); - set.insert(FormatInfo(GL_LUMINANCE32F_EXT, GL_LUMINANCE, GL_FLOAT )); - set.insert(FormatInfo(GL_LUMINANCE_ALPHA32F_EXT, GL_LUMINANCE_ALPHA, GL_FLOAT )); - set.insert(FormatInfo(GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_ALPHA16F_EXT, GL_ALPHA, GL_HALF_FLOAT_OES )); - set.insert(FormatInfo(GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_LUMINANCE16F_EXT, GL_LUMINANCE, GL_HALF_FLOAT_OES )); - set.insert(FormatInfo(GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT )); - set.insert(FormatInfo(GL_LUMINANCE_ALPHA16F_EXT, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES )); - - // From GL_EXT_texture_storage and GL_EXT_texture_format_BGRA8888 - set.insert(FormatInfo(GL_BGRA8_EXT, GL_BGRA_EXT, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT)); - set.insert(FormatInfo(GL_BGRA4_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE )); - set.insert(FormatInfo(GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT)); - set.insert(FormatInfo(GL_BGR5_A1_ANGLEX, GL_BGRA_EXT, GL_UNSIGNED_BYTE )); - - // From GL_ANGLE_depth_texture - set.insert(FormatInfo(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 | - // | | | | - set.insert(FormatInfo(GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_R11_EAC, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_SIGNED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE)); - - - // From GL_EXT_texture_compression_dxt1 - set.insert(FormatInfo(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE)); - set.insert(FormatInfo(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE)); - - // From GL_ANGLE_texture_compression_dxt3 - set.insert(FormatInfo(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE)); - - // From GL_ANGLE_texture_compression_dxt5 - set.insert(FormatInfo(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE)); - - return set; + map->insert(std::make_pair(type, info)); } -static const ES3FormatSet &GetES3FormatSet() +bool operator<(const Type& a, const Type& b) { - static const ES3FormatSet es3FormatSet = BuildES3FormatSet(); - return es3FormatSet; + return memcmp(&a, &b, sizeof(Type)) < 0; } -// Map of sizes of input types -struct TypeInfo -{ - GLuint mTypeBytes; - bool mSpecialInterpretation; - - TypeInfo() - : mTypeBytes(0), mSpecialInterpretation(false) { } - - TypeInfo(GLuint typeBytes, bool specialInterpretation) - : mTypeBytes(typeBytes), mSpecialInterpretation(specialInterpretation) { } - - bool operator<(const TypeInfo& other) const - { - return memcmp(this, &other, sizeof(TypeInfo)) < 0; - } -}; - -typedef std::pair TypeInfoPair; -typedef std::map TypeInfoMap; - static TypeInfoMap BuildTypeInfoMap() { TypeInfoMap map; - map.insert(TypeInfoPair(GL_UNSIGNED_BYTE, TypeInfo( 1, false))); - map.insert(TypeInfoPair(GL_BYTE, TypeInfo( 1, false))); - map.insert(TypeInfoPair(GL_UNSIGNED_SHORT, TypeInfo( 2, false))); - map.insert(TypeInfoPair(GL_SHORT, TypeInfo( 2, false))); - map.insert(TypeInfoPair(GL_UNSIGNED_INT, TypeInfo( 4, false))); - map.insert(TypeInfoPair(GL_INT, TypeInfo( 4, false))); - map.insert(TypeInfoPair(GL_HALF_FLOAT, TypeInfo( 2, false))); - map.insert(TypeInfoPair(GL_HALF_FLOAT_OES, TypeInfo( 2, false))); - map.insert(TypeInfoPair(GL_FLOAT, TypeInfo( 4, false))); - map.insert(TypeInfoPair(GL_UNSIGNED_SHORT_5_6_5, TypeInfo( 2, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_SHORT_4_4_4_4, TypeInfo( 2, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_SHORT_5_5_5_1, TypeInfo( 2, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, TypeInfo( 2, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, TypeInfo( 2, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_INT_2_10_10_10_REV, TypeInfo( 4, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_INT_24_8, TypeInfo( 4, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_INT_10F_11F_11F_REV, TypeInfo( 4, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_INT_5_9_9_9_REV, TypeInfo( 4, true ))); - map.insert(TypeInfoPair(GL_UNSIGNED_INT_24_8_OES, TypeInfo( 4, true ))); - map.insert(TypeInfoPair(GL_FLOAT_32_UNSIGNED_INT_24_8_REV, TypeInfo( 8, true ))); + 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; } -static bool GetTypeInfo(GLenum type, TypeInfo *outTypeInfo) -{ - static const TypeInfoMap infoMap = BuildTypeInfoMap(); - TypeInfoMap::const_iterator iter = infoMap.find(type); - if (iter != infoMap.end()) - { - if (outTypeInfo) - { - *outTypeInfo = iter->second; - } - return true; - } - else - { - return false; - } -} - // Information about internal formats -typedef bool(*SupportCheckFunction)(GLuint, const Extensions &); - static bool AlwaysSupported(GLuint, const Extensions &) { return true; @@ -433,7 +212,7 @@ static bool NeverSupported(GLuint, const Extensions &) } template -static bool RequireESVersion(GLuint clientVersion, const Extensions &) +static bool RequireES(GLuint clientVersion, const Extensions &) { return clientVersion >= minCoreGLVersion; } @@ -443,299 +222,294 @@ typedef bool(Extensions::*ExtensionBool); // Check support for a single extension template -static bool RequireExtension(GLuint, const Extensions & extensions) +static bool RequireExt(GLuint, const Extensions & extensions) { return extensions.*bool1; } // Check for a minimum client version or a single extension template -static bool RequireESVersionOrExtension(GLuint clientVersion, const Extensions &extensions) +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 RequireESVersionOrExtensions(GLuint clientVersion, const Extensions &extensions) +static bool RequireESOrExtAndExt(GLuint clientVersion, const Extensions &extensions) { - return clientVersion >= minCoreGLVersion || (extensions.*bool1 || extensions.*bool2); + return clientVersion >= minCoreGLVersion || (extensions.*bool1 && extensions.*bool2); } -// Check support for two extensions -template -static bool RequireExtensions(GLuint, const Extensions &extensions) +// Check for a minimum client version or at least one of two extensions +template +static bool RequireESOrExtOrExt(GLuint clientVersion, const Extensions &extensions) { - return extensions.*bool1 || extensions.*bool2; + return clientVersion >= minCoreGLVersion || extensions.*bool1 || extensions.*bool2; } -struct InternalFormatInfo -{ - GLuint mRedBits; - GLuint mGreenBits; - GLuint mBlueBits; - - GLuint mLuminanceBits; - - GLuint mAlphaBits; - GLuint mSharedBits; - - GLuint mDepthBits; - GLuint mStencilBits; - - GLuint mPixelBits; - - GLuint mComponentCount; - - GLuint mCompressedBlockWidth; - GLuint mCompressedBlockHeight; - - GLenum mFormat; - GLenum mType; - - GLenum mComponentType; - GLenum mColorEncoding; - - bool mIsCompressed; - - SupportCheckFunction mTextureSupportFunction; - SupportCheckFunction mRenderSupportFunction; - SupportCheckFunction mFilterSupportFunction; - - InternalFormatInfo() : mRedBits(0), mGreenBits(0), mBlueBits(0), mLuminanceBits(0), mAlphaBits(0), mSharedBits(0), mDepthBits(0), mStencilBits(0), - mPixelBits(0), mComponentCount(0), mCompressedBlockWidth(0), mCompressedBlockHeight(0), mFormat(GL_NONE), mType(GL_NONE), - mComponentType(GL_NONE), mColorEncoding(GL_NONE), mIsCompressed(false), mTextureSupportFunction(NeverSupported), - mRenderSupportFunction(NeverSupported), mFilterSupportFunction(NeverSupported) - { - } - - static InternalFormatInfo UnsizedFormat(GLenum format, SupportCheckFunction textureSupport, SupportCheckFunction renderSupport, - SupportCheckFunction filterSupport) - { - InternalFormatInfo formatInfo; - formatInfo.mFormat = format; - formatInfo.mTextureSupportFunction = textureSupport; - formatInfo.mRenderSupportFunction = renderSupport; - formatInfo.mFilterSupportFunction = filterSupport; - return formatInfo; - } - - static InternalFormatInfo RGBAFormat(GLuint red, GLuint green, GLuint blue, GLuint alpha, GLuint shared, - GLenum format, GLenum type, GLenum componentType, bool srgb, - SupportCheckFunction textureSupport, SupportCheckFunction renderSupport, - SupportCheckFunction filterSupport) - { - InternalFormatInfo formatInfo; - formatInfo.mRedBits = red; - formatInfo.mGreenBits = green; - formatInfo.mBlueBits = blue; - formatInfo.mAlphaBits = alpha; - formatInfo.mSharedBits = shared; - formatInfo.mPixelBits = red + green + blue + alpha + shared; - formatInfo.mComponentCount = ((red > 0) ? 1 : 0) + ((green > 0) ? 1 : 0) + ((blue > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0); - formatInfo.mFormat = format; - formatInfo.mType = type; - formatInfo.mComponentType = componentType; - formatInfo.mColorEncoding = (srgb ? GL_SRGB : GL_LINEAR); - formatInfo.mTextureSupportFunction = textureSupport; - formatInfo.mRenderSupportFunction = renderSupport; - formatInfo.mFilterSupportFunction = filterSupport; - return formatInfo; - } - - static InternalFormatInfo LUMAFormat(GLuint luminance, GLuint alpha, GLenum format, GLenum type, GLenum componentType, - SupportCheckFunction textureSupport, SupportCheckFunction renderSupport, - SupportCheckFunction filterSupport) - { - InternalFormatInfo formatInfo; - formatInfo.mLuminanceBits = luminance; - formatInfo.mAlphaBits = alpha; - formatInfo.mPixelBits = luminance + alpha; - formatInfo.mComponentCount = ((luminance > 0) ? 1 : 0) + ((alpha > 0) ? 1 : 0); - formatInfo.mFormat = format; - formatInfo.mType = type; - formatInfo.mComponentType = componentType; - formatInfo.mColorEncoding = GL_LINEAR; - formatInfo.mTextureSupportFunction = textureSupport; - formatInfo.mRenderSupportFunction = renderSupport; - formatInfo.mFilterSupportFunction = filterSupport; - return formatInfo; - } - - static InternalFormatInfo DepthStencilFormat(GLuint depthBits, GLuint stencilBits, GLuint unusedBits, GLenum format, - GLenum type, GLenum componentType, SupportCheckFunction textureSupport, - SupportCheckFunction renderSupport, SupportCheckFunction filterSupport) - { - InternalFormatInfo formatInfo; - formatInfo.mDepthBits = depthBits; - formatInfo.mStencilBits = stencilBits; - formatInfo.mPixelBits = depthBits + stencilBits + unusedBits; - formatInfo.mComponentCount = ((depthBits > 0) ? 1 : 0) + ((stencilBits > 0) ? 1 : 0); - formatInfo.mFormat = format; - formatInfo.mType = type; - formatInfo.mComponentType = componentType; - formatInfo.mColorEncoding = GL_LINEAR; - formatInfo.mTextureSupportFunction = textureSupport; - formatInfo.mRenderSupportFunction = renderSupport; - formatInfo.mFilterSupportFunction = filterSupport; - return formatInfo; - } - - static InternalFormatInfo CompressedFormat(GLuint compressedBlockWidth, GLuint compressedBlockHeight, GLuint compressedBlockSize, - GLuint componentCount, GLenum format, GLenum type, bool srgb, - SupportCheckFunction textureSupport, SupportCheckFunction renderSupport, - SupportCheckFunction filterSupport) - { - InternalFormatInfo formatInfo; - formatInfo.mCompressedBlockWidth = compressedBlockWidth; - formatInfo.mCompressedBlockHeight = compressedBlockHeight; - formatInfo.mPixelBits = compressedBlockSize; - formatInfo.mComponentCount = componentCount; - formatInfo.mFormat = format; - formatInfo.mType = type; - formatInfo.mComponentType = GL_UNSIGNED_NORMALIZED; - formatInfo.mColorEncoding = (srgb ? GL_SRGB : GL_LINEAR); - formatInfo.mIsCompressed = true; - formatInfo.mTextureSupportFunction = textureSupport; - formatInfo.mRenderSupportFunction = renderSupport; - formatInfo.mFilterSupportFunction = filterSupport; - return formatInfo; - } -}; - -typedef std::pair InternalFormatInfoPair; -typedef std::map InternalFormatInfoMap; +// 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, InternalFormatInfo())); - - // | Internal format | | R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Renderable | Filterable | - map.insert(InternalFormatInfoPair(GL_R8, InternalFormatInfo::RGBAFormat( 8, 0, 0, 0, 0, GL_RED, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESVersionOrExtension<3, &Extensions::textureRG>, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_R8_SNORM, InternalFormatInfo::RGBAFormat( 8, 0, 0, 0, 0, GL_RED, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireESVersion<3>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RG8, InternalFormatInfo::RGBAFormat( 8, 8, 0, 0, 0, GL_RG, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESVersionOrExtension<3, &Extensions::textureRG>, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RG8_SNORM, InternalFormatInfo::RGBAFormat( 8, 8, 0, 0, 0, GL_RG, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireESVersion<3>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB8, InternalFormatInfo::RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESVersionOrExtension<3, &Extensions::rgb8rgba8>, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB8_SNORM, InternalFormatInfo::RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireESVersion<3>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB565, InternalFormatInfo::RGBAFormat( 5, 6, 5, 0, 0, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_UNSIGNED_NORMALIZED, false, RequireESVersion<2>, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA4, InternalFormatInfo::RGBAFormat( 4, 4, 4, 4, 0, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_UNSIGNED_NORMALIZED, false, RequireESVersion<2>, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB5_A1, InternalFormatInfo::RGBAFormat( 5, 5, 5, 1, 0, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_UNSIGNED_NORMALIZED, false, RequireESVersion<2>, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA8, InternalFormatInfo::RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireESVersionOrExtension<3, &Extensions::rgb8rgba8>, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA8_SNORM, InternalFormatInfo::RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_BYTE, GL_SIGNED_NORMALIZED, false, RequireESVersion<3>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB10_A2, InternalFormatInfo::RGBAFormat(10, 10, 10, 2, 0, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, RequireESVersion<3>, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB10_A2UI, InternalFormatInfo::RGBAFormat(10, 10, 10, 2, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_INT, false, RequireESVersion<3>, NeverSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_SRGB8, InternalFormatInfo::RGBAFormat( 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESVersionOrExtension<3, &Extensions::sRGB>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_SRGB8_ALPHA8, InternalFormatInfo::RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, true, RequireESVersionOrExtension<3, &Extensions::sRGB>, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_R11F_G11F_B10F, InternalFormatInfo::RGBAFormat(11, 11, 10, 0, 0, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_FLOAT, false, RequireESVersion<3>, RequireExtension<&Extensions::colorBufferFloat>, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB9_E5, InternalFormatInfo::RGBAFormat( 9, 9, 9, 0, 5, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_FLOAT, false, RequireESVersion<3>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_R8I, InternalFormatInfo::RGBAFormat( 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_BYTE, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_R8UI, InternalFormatInfo::RGBAFormat( 8, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_R16I, InternalFormatInfo::RGBAFormat(16, 0, 0, 0, 0, GL_RED_INTEGER, GL_SHORT, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_R16UI, InternalFormatInfo::RGBAFormat(16, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_R32I, InternalFormatInfo::RGBAFormat(32, 0, 0, 0, 0, GL_RED_INTEGER, GL_INT, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_R32UI, InternalFormatInfo::RGBAFormat(32, 0, 0, 0, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RG8I, InternalFormatInfo::RGBAFormat( 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_BYTE, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RG8UI, InternalFormatInfo::RGBAFormat( 8, 8, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RG16I, InternalFormatInfo::RGBAFormat(16, 16, 0, 0, 0, GL_RG_INTEGER, GL_SHORT, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RG16UI, InternalFormatInfo::RGBAFormat(16, 16, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RG32I, InternalFormatInfo::RGBAFormat(32, 32, 0, 0, 0, GL_RG_INTEGER, GL_INT, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RG32UI, InternalFormatInfo::RGBAFormat(32, 32, 0, 0, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGB8I, InternalFormatInfo::RGBAFormat( 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_BYTE, GL_INT, false, RequireESVersion<3>, NeverSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGB8UI, InternalFormatInfo::RGBAFormat( 8, 8, 8, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireESVersion<3>, NeverSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGB16I, InternalFormatInfo::RGBAFormat(16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_SHORT, GL_INT, false, RequireESVersion<3>, NeverSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGB16UI, InternalFormatInfo::RGBAFormat(16, 16, 16, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireESVersion<3>, NeverSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGB32I, InternalFormatInfo::RGBAFormat(32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_INT, GL_INT, false, RequireESVersion<3>, NeverSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGB32UI, InternalFormatInfo::RGBAFormat(32, 32, 32, 0, 0, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireESVersion<3>, NeverSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA8I, InternalFormatInfo::RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_BYTE, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA8UI, InternalFormatInfo::RGBAFormat( 8, 8, 8, 8, 0, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA16I, InternalFormatInfo::RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_SHORT, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA16UI, InternalFormatInfo::RGBAFormat(16, 16, 16, 16, 0, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA32I, InternalFormatInfo::RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_INT, GL_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA32UI, InternalFormatInfo::RGBAFormat(32, 32, 32, 32, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_UNSIGNED_INT, false, RequireESVersion<3>, AlwaysSupported, NeverSupported))); - - map.insert(InternalFormatInfoPair(GL_BGRA8_EXT, InternalFormatInfo::RGBAFormat( 8, 8, 8, 8, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, RequireExtension<&Extensions::textureFormatBGRA8888>, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_BGRA4_ANGLEX, InternalFormatInfo::RGBAFormat( 4, 4, 4, 4, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExtension<&Extensions::textureFormatBGRA8888>, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_BGR5_A1_ANGLEX, InternalFormatInfo::RGBAFormat( 5, 5, 5, 1, 0, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_UNSIGNED_NORMALIZED, false, RequireExtension<&Extensions::textureFormatBGRA8888>, AlwaysSupported, AlwaysSupported))); + 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, InternalFormatInfo::RGBAFormat(16, 0, 0, 0, 0, GL_RED, GL_HALF_FLOAT, GL_FLOAT, false, RequireESVersionOrExtensions<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, AlwaysSupported, RequireExtension<&Extensions::textureHalfFloatLinear>))); - map.insert(InternalFormatInfoPair(GL_RG16F, InternalFormatInfo::RGBAFormat(16, 16, 0, 0, 0, GL_RG, GL_HALF_FLOAT, GL_FLOAT, false, RequireESVersionOrExtensions<3, &Extensions::textureHalfFloat, &Extensions::textureRG>, AlwaysSupported, RequireExtension<&Extensions::textureHalfFloatLinear>))); - map.insert(InternalFormatInfoPair(GL_RGB16F, InternalFormatInfo::RGBAFormat(16, 16, 16, 0, 0, GL_RGB, GL_HALF_FLOAT, GL_FLOAT, false, RequireESVersionOrExtension<3, &Extensions::textureHalfFloat>, AlwaysSupported, RequireExtension<&Extensions::textureHalfFloatLinear>))); - map.insert(InternalFormatInfoPair(GL_RGBA16F, InternalFormatInfo::RGBAFormat(16, 16, 16, 16, 0, GL_RGBA, GL_HALF_FLOAT, GL_FLOAT, false, RequireESVersionOrExtension<3, &Extensions::textureHalfFloat>, AlwaysSupported, RequireExtension<&Extensions::textureHalfFloatLinear>))); - map.insert(InternalFormatInfoPair(GL_R32F, InternalFormatInfo::RGBAFormat(32, 0, 0, 0, 0, GL_RED, GL_FLOAT, GL_FLOAT, false, RequireESVersionOrExtensions<3, &Extensions::textureFloat, &Extensions::textureRG>, AlwaysSupported, RequireExtension<&Extensions::textureFloatLinear> ))); - map.insert(InternalFormatInfoPair(GL_RG32F, InternalFormatInfo::RGBAFormat(32, 32, 0, 0, 0, GL_RG, GL_FLOAT, GL_FLOAT, false, RequireESVersionOrExtensions<3, &Extensions::textureFloat, &Extensions::textureRG>, AlwaysSupported, RequireExtension<&Extensions::textureFloatLinear> ))); - map.insert(InternalFormatInfoPair(GL_RGB32F, InternalFormatInfo::RGBAFormat(32, 32, 32, 0, 0, GL_RGB, GL_FLOAT, GL_FLOAT, false, RequireESVersionOrExtension<3, &Extensions::textureFloat>, AlwaysSupported, RequireExtension<&Extensions::textureFloatLinear> ))); - map.insert(InternalFormatInfoPair(GL_RGBA32F, InternalFormatInfo::RGBAFormat(32, 32, 32, 32, 0, GL_RGBA, GL_FLOAT, GL_FLOAT, false, RequireESVersionOrExtension<3, &Extensions::textureFloat>, AlwaysSupported, RequireExtension<&Extensions::textureFloatLinear> ))); + // | 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 | - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT16, InternalFormatInfo::DepthStencilFormat(16, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_UNSIGNED_NORMALIZED, RequireESVersion<2>, AlwaysSupported, RequireESVersionOrExtension<3, &Extensions::depthTextures>))); - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT24, InternalFormatInfo::DepthStencilFormat(24, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireESVersion<3>, AlwaysSupported, RequireESVersionOrExtension<3, &Extensions::depthTextures>))); - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32F, InternalFormatInfo::DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_FLOAT, GL_FLOAT, RequireESVersion<3>, AlwaysSupported, RequireESVersionOrExtension<3, &Extensions::depthTextures>))); - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES, InternalFormatInfo::DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExtension<&Extensions::depthTextures>, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_DEPTH24_STENCIL8, InternalFormatInfo::DepthStencilFormat(24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESVersionOrExtension<2, &Extensions::depthTextures>, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_DEPTH32F_STENCIL8, InternalFormatInfo::DepthStencilFormat(32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, RequireESVersion<3>, AlwaysSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_STENCIL_INDEX8, InternalFormatInfo::DepthStencilFormat( 0, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, RequireESVersion<2>, AlwaysSupported, NeverSupported ))); + // | 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, InternalFormatInfo::LUMAFormat( 0, 8, GL_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExtension<&Extensions::textureStorage>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE8_EXT, InternalFormatInfo::LUMAFormat( 8, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExtension<&Extensions::textureStorage>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_ALPHA32F_EXT, InternalFormatInfo::LUMAFormat( 0, 32, GL_ALPHA, GL_FLOAT, GL_FLOAT, RequireExtensions<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE32F_EXT, InternalFormatInfo::LUMAFormat(32, 0, GL_LUMINANCE, GL_FLOAT, GL_FLOAT, RequireExtensions<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_ALPHA16F_EXT, InternalFormatInfo::LUMAFormat( 0, 16, GL_ALPHA, GL_HALF_FLOAT, GL_FLOAT, RequireExtensions<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE16F_EXT, InternalFormatInfo::LUMAFormat(16, 0, GL_LUMINANCE, GL_HALF_FLOAT, GL_FLOAT, RequireExtensions<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE8_ALPHA8_EXT, InternalFormatInfo::LUMAFormat( 8, 8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireExtension<&Extensions::textureStorage>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA32F_EXT, InternalFormatInfo::LUMAFormat(32, 32, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_FLOAT, RequireExtensions<&Extensions::textureStorage, &Extensions::textureFloat>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA16F_EXT, InternalFormatInfo::LUMAFormat(16, 16, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_FLOAT, RequireExtensions<&Extensions::textureStorage, &Extensions::textureHalfFloat>, NeverSupported, AlwaysSupported))); + // | 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, InternalFormatInfo::UnsizedFormat(GL_ALPHA, RequireESVersion<2>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE, InternalFormatInfo::UnsizedFormat(GL_LUMINANCE, RequireESVersion<2>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_LUMINANCE_ALPHA, InternalFormatInfo::UnsizedFormat(GL_LUMINANCE_ALPHA, RequireESVersion<2>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RED, InternalFormatInfo::UnsizedFormat(GL_RED, RequireESVersionOrExtension<3, &Extensions::textureRG>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RG, InternalFormatInfo::UnsizedFormat(GL_RG, RequireESVersionOrExtension<3, &Extensions::textureRG>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGB, InternalFormatInfo::UnsizedFormat(GL_RGB, RequireESVersion<2>, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RGBA, InternalFormatInfo::UnsizedFormat(GL_RGBA, RequireESVersion<2>, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_RED_INTEGER, InternalFormatInfo::UnsizedFormat(GL_RED_INTEGER, RequireESVersion<3>, NeverSupported, NeverSupported ))); - map.insert(InternalFormatInfoPair(GL_RG_INTEGER, InternalFormatInfo::UnsizedFormat(GL_RG_INTEGER, RequireESVersion<3>, NeverSupported, NeverSupported ))); - map.insert(InternalFormatInfoPair(GL_RGB_INTEGER, InternalFormatInfo::UnsizedFormat(GL_RGB_INTEGER, RequireESVersion<3>, NeverSupported, NeverSupported ))); - map.insert(InternalFormatInfoPair(GL_RGBA_INTEGER, InternalFormatInfo::UnsizedFormat(GL_RGBA_INTEGER, RequireESVersion<3>, NeverSupported, NeverSupported ))); - map.insert(InternalFormatInfoPair(GL_BGRA_EXT, InternalFormatInfo::UnsizedFormat(GL_BGRA_EXT, RequireExtension<&Extensions::textureFormatBGRA8888>, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT, InternalFormatInfo::UnsizedFormat(GL_DEPTH_COMPONENT, RequireESVersion<2>, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_DEPTH_STENCIL, InternalFormatInfo::UnsizedFormat(GL_DEPTH_STENCIL, RequireESVersionOrExtension<3, &Extensions::packedDepthStencil>, AlwaysSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_SRGB_EXT, InternalFormatInfo::UnsizedFormat(GL_RGB, RequireESVersionOrExtension<3, &Extensions::sRGB>, NeverSupported, AlwaysSupported))); - map.insert(InternalFormatInfoPair(GL_SRGB_ALPHA_EXT, InternalFormatInfo::UnsizedFormat(GL_RGBA, RequireESVersionOrExtension<3, &Extensions::sRGB>, AlwaysSupported, AlwaysSupported))); + // | 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, InternalFormatInfo::CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_R11_EAC, InternalFormatInfo::CompressedFormat(4, 4, 64, 1, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RG11_EAC, InternalFormatInfo::CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SIGNED_RG11_EAC, InternalFormatInfo::CompressedFormat(4, 4, 128, 2, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGB8_ETC2, InternalFormatInfo::CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, false, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_SRGB8_ETC2, InternalFormatInfo::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, InternalFormatInfo::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, InternalFormatInfo::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, InternalFormatInfo::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, InternalFormatInfo::CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, true, UnimplementedSupport, UnimplementedSupport, UnimplementedSupport))); + // | 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, InternalFormatInfo::CompressedFormat(4, 4, 64, 3, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, RequireExtension<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported ))); - map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, InternalFormatInfo::CompressedFormat(4, 4, 64, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, false, RequireExtension<&Extensions::textureCompressionDXT1>, NeverSupported, AlwaysSupported ))); + // | 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, InternalFormatInfo::CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, false, RequireExtension<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported ))); + 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, InternalFormatInfo::CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, false, RequireExtension<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported ))); + 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; } @@ -746,24 +520,6 @@ static const InternalFormatInfoMap &GetInternalFormatMap() return formatMap; } -static bool GetInternalFormatInfo(GLenum internalFormat, InternalFormatInfo *outFormatInfo) -{ - const InternalFormatInfoMap &map = GetInternalFormatMap(); - InternalFormatInfoMap::const_iterator iter = map.find(internalFormat); - if (iter != map.end()) - { - if (outFormatInfo) - { - *outFormatInfo = iter->second; - } - return true; - } - else - { - return false; - } -} - static FormatSet BuildAllSizedInternalFormatSet() { FormatSet result; @@ -771,7 +527,7 @@ static FormatSet BuildAllSizedInternalFormatSet() const InternalFormatInfoMap &formats = GetInternalFormatMap(); for (InternalFormatInfoMap::const_iterator i = formats.begin(); i != formats.end(); i++) { - if (i->second.mPixelBits > 0) + if (i->second.pixelBytes > 0) { result.insert(i->first); } @@ -780,756 +536,88 @@ static FormatSet BuildAllSizedInternalFormatSet() return result; } -typedef std::set TypeSet; - -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 InternalFormatInfo &srcFormat, const InternalFormatInfo &destFormat, - GLenum *outEffectiveFormat) -{ - const EffectiveInternalFormatList *list = NULL; - GLenum targetFormat = GL_NONE; - - if (gl::IsSizedInternalFormat(destFormat.mFormat)) - { - static const EffectiveInternalFormatList sizedList = BuildSizedEffectiveInternalFormatList(); - list = &sizedList; - } - else - { - static const EffectiveInternalFormatList unsizedList = BuildUnsizedEffectiveInternalFormatList(); - list = &unsizedList; - targetFormat = destFormat.mFormat; - } - - for (size_t curFormat = 0; curFormat < list->size(); ++curFormat) - { - const EffectiveInternalFormatInfo& formatInfo = list->at(curFormat); - if ((formatInfo.mDestFormat == targetFormat) && - (formatInfo.mMinRedBits <= srcFormat.mRedBits && formatInfo.mMaxRedBits >= srcFormat.mRedBits) && - (formatInfo.mMinGreenBits <= srcFormat.mGreenBits && formatInfo.mMaxGreenBits >= srcFormat.mGreenBits) && - (formatInfo.mMinBlueBits <= srcFormat.mBlueBits && formatInfo.mMaxBlueBits >= srcFormat.mBlueBits) && - (formatInfo.mMinAlphaBits <= srcFormat.mAlphaBits && formatInfo.mMaxAlphaBits >= srcFormat.mAlphaBits)) - { - *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; -} - -bool IsValidInternalFormat(GLenum internalFormat, const Extensions &extensions, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - ASSERT(internalFormatInfo.mTextureSupportFunction != NULL); - return internalFormatInfo.mTextureSupportFunction(clientVersion, extensions); - } - else - { - return false; - } -} - -bool IsValidFormat(GLenum format, const Extensions &extensions, GLuint clientVersion) -{ - const InternalFormatInfoMap &internalFormats = GetInternalFormatMap(); - for (InternalFormatInfoMap::const_iterator i = internalFormats.begin(); i != internalFormats.end(); i++) - { - if (i->second.mFormat == format && i->second.mTextureSupportFunction(clientVersion, extensions)) - { - return true; - } - } - - return false; -} - -bool IsValidType(GLenum type, const Extensions &extensions, GLuint clientVersion) +const FormatType &GetFormatTypeInfo(GLenum format, GLenum type) { - const InternalFormatInfoMap &internalFormats = GetInternalFormatMap(); - for (InternalFormatInfoMap::const_iterator i = internalFormats.begin(); i != internalFormats.end(); i++) + static const FormatMap formatMap = BuildFormatMap(); + FormatMap::const_iterator iter = formatMap.find(FormatTypePair(format, type)); + if (iter != formatMap.end()) { - if (i->second.mType == type && i->second.mTextureSupportFunction(clientVersion, extensions)) - { - return true; - } - } - - return false; -} - -bool IsValidFormatCombination(GLenum internalFormat, GLenum format, GLenum type, const Extensions &extensions, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - if (!internalFormatInfo.mTextureSupportFunction(clientVersion, extensions)) - { - return false; - } + return iter->second; } else { - UNREACHABLE(); - return false; - } - - if (clientVersion == 2) - { - static const FormatMap &formats = GetFormatMap(); - FormatMap::const_iterator iter = formats.find(FormatTypePair(format, type)); - return (iter != formats.end()) && ((internalFormat == (GLint)type) || (internalFormat == iter->second.mInternalFormat)); - } - else if (clientVersion == 3) - { - static const ES3FormatSet &formats = GetES3FormatSet(); - return formats.find(FormatInfo(internalFormat, format, type)) != formats.end(); - } - else - { - UNREACHABLE(); - return false; + static const FormatType defaultInfo; + return defaultInfo; } } -bool IsValidCopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle, GLuint clientVersion) +const Type &GetTypeInfo(GLenum type) { - InternalFormatInfo textureInternalFormatInfo; - InternalFormatInfo framebufferInternalFormatInfo; - if (GetInternalFormatInfo(textureInternalFormat, &textureInternalFormatInfo) && - GetInternalFormatInfo(frameBufferInternalFormat, &framebufferInternalFormatInfo)) - { - if (clientVersion == 2) - { - UNIMPLEMENTED(); - return false; - } - else if (clientVersion == 3) - { - static const CopyConversionSet conversionSet = BuildValidES3CopyTexImageCombinations(); - const CopyConversion conversion = CopyConversion(textureInternalFormatInfo.mFormat, - framebufferInternalFormatInfo.mFormat); - if (conversionSet.find(conversion) != 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.mColorEncoding == GL_SRGB) != (framebufferInternalFormatInfo.mColorEncoding == GL_SRGB)) - { - return false; - } - - if (((textureInternalFormatInfo.mComponentType == GL_INT) != (framebufferInternalFormatInfo.mComponentType == GL_INT)) || - ((textureInternalFormatInfo.mComponentType == GL_UNSIGNED_INT) != (framebufferInternalFormatInfo.mComponentType == GL_UNSIGNED_INT))) - { - return false; - } - - if (gl::IsFloatOrFixedComponentType(textureInternalFormatInfo.mComponentType) && - !gl::IsFloatOrFixedComponentType(framebufferInternalFormatInfo.mComponentType)) - { - 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. - InternalFormatInfo sourceEffectiveFormat; - if (readBufferHandle != 0) - { - // Not the default framebuffer, therefore the read buffer must be a user-created texture or renderbuffer - if (gl::IsSizedInternalFormat(framebufferInternalFormatInfo.mFormat)) - { - 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 effectiveFormat = gl::GetSizedInternalFormat(framebufferInternalFormatInfo.mFormat, - framebufferInternalFormatInfo.mType); - gl::GetInternalFormatInfo(effectiveFormat, &sourceEffectiveFormat); - } - } - 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.mColorEncoding == GL_LINEAR) - { - GLenum effectiveFormat; - if (GetEffectiveInternalFormat(framebufferInternalFormatInfo, textureInternalFormatInfo, &effectiveFormat)) - { - gl::GetInternalFormatInfo(effectiveFormat, &sourceEffectiveFormat); - } - else - { - return false; - } - } - else if (framebufferInternalFormatInfo.mColorEncoding == GL_SRGB) - { - // SRGB buffers can only be copied to sized format destinations according to table 3.18 - if (gl::IsSizedInternalFormat(textureInternalFormat) && - (framebufferInternalFormatInfo.mRedBits >= 1 && framebufferInternalFormatInfo.mRedBits <= 8) && - (framebufferInternalFormatInfo.mGreenBits >= 1 && framebufferInternalFormatInfo.mGreenBits <= 8) && - (framebufferInternalFormatInfo.mBlueBits >= 1 && framebufferInternalFormatInfo.mBlueBits <= 8) && - (framebufferInternalFormatInfo.mAlphaBits >= 1 && framebufferInternalFormatInfo.mAlphaBits <= 8)) - { - gl::GetInternalFormatInfo(GL_SRGB8_ALPHA8, &sourceEffectiveFormat); - } - else - { - return false; - } - } - else - { - UNREACHABLE(); - } - } - - if (gl::IsSizedInternalFormat(textureInternalFormatInfo.mFormat)) - { - // 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.mRedBits != sourceEffectiveFormat.mRedBits || - textureInternalFormatInfo.mGreenBits != sourceEffectiveFormat.mGreenBits || - textureInternalFormatInfo.mBlueBits != sourceEffectiveFormat.mBlueBits || - textureInternalFormatInfo.mAlphaBits != sourceEffectiveFormat.mAlphaBits) - { - return false; - } - } - - - return true; // A conversion function exists, and no rule in the specification has precluded conversion - // between these formats. - } - - return false; - } - else - { - UNREACHABLE(); - return false; - } - } - else - { - UNREACHABLE(); - return false; - } -} - -bool IsRenderingSupported(GLenum internalFormat, const Extensions &extensions, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - ASSERT(internalFormatInfo.mTextureSupportFunction != NULL); - ASSERT(internalFormatInfo.mRenderSupportFunction != NULL); - return internalFormatInfo.mTextureSupportFunction(clientVersion, extensions) && - internalFormatInfo.mRenderSupportFunction(clientVersion, extensions); - } - else - { - return false; - } -} - -bool IsFilteringSupported(GLenum internalFormat, const Extensions &extensions, GLuint clientVersion) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - ASSERT(internalFormatInfo.mTextureSupportFunction != NULL); - ASSERT(internalFormatInfo.mFilterSupportFunction != NULL); - return internalFormatInfo.mTextureSupportFunction(clientVersion, extensions) && - internalFormatInfo.mFilterSupportFunction(clientVersion, extensions); - } - else - { - return false; - } -} - -bool IsSizedInternalFormat(GLenum internalFormat) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - return internalFormatInfo.mPixelBits > 0; - } - else - { - UNREACHABLE(); - return false; - } -} - -GLenum GetSizedInternalFormat(GLenum format, GLenum type) -{ - const FormatMap &formats = GetFormatMap(); - FormatMap::const_iterator iter = formats.find(FormatTypePair(format, type)); - return (iter != formats.end()) ? iter->second.mInternalFormat : GL_NONE; -} - -GLuint GetPixelBytes(GLenum internalFormat) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - return internalFormatInfo.mPixelBits / 8; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetAlphaBits(GLenum internalFormat) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - return internalFormatInfo.mAlphaBits; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetRedBits(GLenum internalFormat) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - return internalFormatInfo.mRedBits; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetGreenBits(GLenum internalFormat) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - return internalFormatInfo.mGreenBits; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetBlueBits(GLenum internalFormat) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - return internalFormatInfo.mBlueBits; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetLuminanceBits(GLenum internalFormat) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - return internalFormatInfo.mLuminanceBits; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetDepthBits(GLenum internalFormat) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - return internalFormatInfo.mDepthBits; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetStencilBits(GLenum internalFormat) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - return internalFormatInfo.mStencilBits; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetTypeBytes(GLenum type) -{ - TypeInfo typeInfo; - if (GetTypeInfo(type, &typeInfo)) - { - return typeInfo.mTypeBytes; - } - else - { - UNREACHABLE(); - return 0; - } -} - -bool IsSpecialInterpretationType(GLenum type) -{ - TypeInfo typeInfo; - if (GetTypeInfo(type, &typeInfo)) - { - return typeInfo.mSpecialInterpretation; - } - else - { - UNREACHABLE(); - return false; - } -} - -bool IsFloatOrFixedComponentType(GLenum type) -{ - if (type == GL_UNSIGNED_NORMALIZED || - type == GL_SIGNED_NORMALIZED || - type == GL_FLOAT) + static const TypeInfoMap infoMap = BuildTypeInfoMap(); + TypeInfoMap::const_iterator iter = infoMap.find(type); + if (iter != infoMap.end()) { - return true; + return iter->second; } else { - return false; + static const Type defaultInfo; + return defaultInfo; } } -GLenum GetFormat(GLenum internalFormat) +const InternalFormat &GetInternalFormatInfo(GLenum internalFormat) { - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) + const InternalFormatInfoMap &formatMap = GetInternalFormatMap(); + InternalFormatInfoMap::const_iterator iter = formatMap.find(internalFormat); + if (iter != formatMap.end()) { - return internalFormatInfo.mFormat; + return iter->second; } else { - UNREACHABLE(); - return GL_NONE; + static const InternalFormat defaultInternalFormat; + return defaultInternalFormat; } } -GLenum GetType(GLenum internalFormat) +GLuint InternalFormat::computeRowPitch(GLenum type, GLsizei width, GLint alignment) const { - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - return internalFormatInfo.mType; - } - else - { - UNREACHABLE(); - return GL_NONE; - } + ASSERT(alignment > 0 && isPow2(alignment)); + return rx::roundUp(computeBlockSize(type, width, 1), static_cast(alignment)); } -GLenum GetComponentType(GLenum internalFormat) +GLuint InternalFormat::computeDepthPitch(GLenum type, GLsizei width, GLsizei height, GLint alignment) const { - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - return internalFormatInfo.mComponentType; - } - else - { - UNREACHABLE(); - return GL_NONE; - } + return computeRowPitch(type, width, alignment) * height; } -GLuint GetComponentCount(GLenum internalFormat) +GLuint InternalFormat::computeBlockSize(GLenum type, GLsizei width, GLsizei height) const { - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) + if (compressed) { - return internalFormatInfo.mComponentCount; + GLsizei numBlocksWide = (width + compressedBlockWidth - 1) / compressedBlockWidth; + GLsizei numBlocksHight = (height + compressedBlockHeight - 1) / compressedBlockHeight; + return (pixelBytes * numBlocksWide * numBlocksHight); } else { - UNREACHABLE(); - return false; - } -} - -GLenum GetColorEncoding(GLenum internalFormat) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - return internalFormatInfo.mColorEncoding; - } - else - { - UNREACHABLE(); - return false; - } -} - -GLuint GetRowPitch(GLenum internalFormat, GLenum type, GLsizei width, GLint alignment) -{ - ASSERT(alignment > 0 && isPow2(alignment)); - return rx::roundUp(GetBlockSize(internalFormat, type, width, 1), static_cast(alignment)); -} - -GLuint GetDepthPitch(GLenum internalFormat, GLenum type, GLsizei width, GLsizei height, GLint alignment) -{ - return GetRowPitch(internalFormat, type, width, alignment) * height; -} - -GLuint GetBlockSize(GLenum internalFormat, GLenum type, GLsizei width, GLsizei height) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - if (internalFormatInfo.mIsCompressed) + const Type &typeInfo = GetTypeInfo(type); + if (typeInfo.specialInterpretation) { - GLsizei numBlocksWide = (width + internalFormatInfo.mCompressedBlockWidth - 1) / internalFormatInfo.mCompressedBlockWidth; - GLsizei numBlocksHight = (height + internalFormatInfo.mCompressedBlockHeight - 1) / internalFormatInfo.mCompressedBlockHeight; - - return (internalFormatInfo.mPixelBits * numBlocksWide * numBlocksHight) / 8; + return typeInfo.bytes * width * height; } else { - TypeInfo typeInfo; - if (GetTypeInfo(type, &typeInfo)) - { - if (typeInfo.mSpecialInterpretation) - { - return typeInfo.mTypeBytes * width * height; - } - else - { - return internalFormatInfo.mComponentCount * typeInfo.mTypeBytes * width * height; - } - } - else - { - UNREACHABLE(); - return 0; - } + return componentCount * typeInfo.bytes * width * height; } } - else - { - UNREACHABLE(); - return 0; - } -} - -bool IsFormatCompressed(GLenum internalFormat) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - return internalFormatInfo.mIsCompressed; - } - else - { - UNREACHABLE(); - return false; - } } -GLuint GetCompressedBlockWidth(GLenum internalFormat) +GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type) { - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - return internalFormatInfo.mCompressedBlockWidth; - } - else - { - UNREACHABLE(); - return 0; - } -} - -GLuint GetCompressedBlockHeight(GLenum internalFormat) -{ - InternalFormatInfo internalFormatInfo; - if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) - { - return internalFormatInfo.mCompressedBlockHeight; - } - else - { - UNREACHABLE(); - return 0; - } + const InternalFormat& formatInfo = GetInternalFormatInfo(internalFormat); + return (formatInfo.pixelBytes > 0) ? internalFormat : GetFormatTypeInfo(internalFormat, type).internalFormat; } const FormatSet &GetAllSizedInternalFormats() @@ -1538,11 +626,4 @@ const FormatSet &GetAllSizedInternalFormats() return formatSet; } -ColorWriteFunction GetColorWriteFunction(GLenum format, GLenum type) -{ - static const FormatMap &formats = GetFormatMap(); - FormatMap::const_iterator iter = formats.find(FormatTypePair(format, type)); - return (iter != formats.end()) ? iter->second.mColorWriteFunction : NULL; -} - } diff --git a/src/3rdparty/angle/src/libGLESv2/formatutils.h b/src/3rdparty/angle/src/libGLESv2/formatutils.h index 2f592798b8..25106a52e5 100644 --- a/src/3rdparty/angle/src/libGLESv2/formatutils.h +++ b/src/3rdparty/angle/src/libGLESv2/formatutils.h @@ -9,12 +9,13 @@ #ifndef LIBGLESV2_FORMATUTILS_H_ #define LIBGLESV2_FORMATUTILS_H_ -#include "angle_gl.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, @@ -27,61 +28,78 @@ typedef void (*LoadImageFunction)(size_t width, size_t height, size_t depth, 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 void *source, void *dest); -typedef void (*ColorWriteFunction)(const void *source, void *dest); -typedef void (*ColorCopyFunction)(const void *source, void *dest); +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 void *input, size_t stride, size_t count, void *output); +typedef void (*VertexCopyFunction)(const uint8_t *input, size_t stride, size_t count, uint8_t *output); namespace gl { -typedef std::set FormatSet; +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); -bool IsValidInternalFormat(GLenum internalFormat, const Extensions &extensions, GLuint clientVersion); -bool IsValidFormat(GLenum format, const Extensions &extensions, GLuint clientVersion); -bool IsValidType(GLenum type, const Extensions &extensions, GLuint clientVersion); +struct InternalFormat +{ + InternalFormat(); -bool IsValidFormatCombination(GLenum internalFormat, GLenum format, GLenum type, const Extensions &extensions, GLuint clientVersion); -bool IsValidCopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle, GLuint clientVersion); + GLuint redBits; + GLuint greenBits; + GLuint blueBits; -bool IsRenderingSupported(GLenum internalFormat, const Extensions &extensions, GLuint clientVersion); -bool IsFilteringSupported(GLenum internalFormat, const Extensions &extensions, GLuint clientVersion); + GLuint luminanceBits; -bool IsSizedInternalFormat(GLenum internalFormat); -GLenum GetSizedInternalFormat(GLenum format, GLenum type); + GLuint alphaBits; + GLuint sharedBits; -GLuint GetPixelBytes(GLenum internalFormat); -GLuint GetAlphaBits(GLenum internalFormat); -GLuint GetRedBits(GLenum internalFormat); -GLuint GetGreenBits(GLenum internalFormat); -GLuint GetBlueBits(GLenum internalFormat); -GLuint GetLuminanceBits(GLenum internalFormat); -GLuint GetDepthBits(GLenum internalFormat); -GLuint GetStencilBits(GLenum internalFormat); + GLuint depthBits; + GLuint stencilBits; -GLuint GetTypeBytes(GLenum type); -bool IsSpecialInterpretationType(GLenum type); -bool IsFloatOrFixedComponentType(GLenum type); + GLuint pixelBytes; -GLenum GetFormat(GLenum internalFormat); -GLenum GetType(GLenum internalFormat); + GLuint componentCount; -GLenum GetComponentType(GLenum internalFormat); -GLuint GetComponentCount(GLenum internalFormat); -GLenum GetColorEncoding(GLenum internalFormat); + bool compressed; + GLuint compressedBlockWidth; + GLuint compressedBlockHeight; -GLuint GetRowPitch(GLenum internalFormat, GLenum type, GLsizei width, GLint alignment); -GLuint GetDepthPitch(GLenum internalFormat, GLenum type, GLsizei width, GLsizei height, GLint alignment); -GLuint GetBlockSize(GLenum internalFormat, GLenum type, GLsizei width, GLsizei height); + GLenum format; + GLenum type; -bool IsFormatCompressed(GLenum internalFormat); -GLuint GetCompressedBlockWidth(GLenum internalFormat); -GLuint GetCompressedBlockHeight(GLenum internalFormat); + GLenum componentType; + GLenum colorEncoding; -const FormatSet &GetAllSizedInternalFormats(); + typedef bool (*SupportCheckFunction)(GLuint, const Extensions &); + SupportCheckFunction textureSupport; + SupportCheckFunction renderSupport; + SupportCheckFunction filterSupport; -ColorWriteFunction GetColorWriteFunction(GLenum format, GLenum type); + 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(); } diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp index 5e2ec4a4ee..07f5d47473 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -7,10 +6,14 @@ // 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 "common/utilities.h" #include "libGLESv2/formatutils.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Fence.h" @@ -31,6 +34,7 @@ #include "libGLESv2/validationES3.h" #include "libGLESv2/queryconversions.h" + extern "C" { @@ -41,12 +45,12 @@ void __stdcall glActiveTexture(GLenum texture) EVENT("(GLenum texture = 0x%X)", texture); gl::Context *context = gl::getNonLostContext(); - if (context) { - if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getMaximumCombinedTextureImageUnits() - 1) + if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } context->getState().setActiveSampler(texture - GL_TEXTURE0); @@ -58,7 +62,6 @@ void __stdcall 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); @@ -68,11 +71,13 @@ void __stdcall glAttachShader(GLuint program, GLuint shader) { if (context->getShader(program)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } @@ -80,17 +85,20 @@ void __stdcall glAttachShader(GLuint program, GLuint shader) { if (context->getProgram(shader)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } if (!programObject->attachShader(shaderObject)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } } } @@ -100,7 +108,6 @@ void __stdcall 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)) @@ -108,7 +115,12 @@ void __stdcall glBeginQueryEXT(GLenum target, GLuint id) return; } - context->beginQuery(target, id); + gl::Error error = context->beginQuery(target, id); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -116,32 +128,35 @@ void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* { EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name); - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - 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)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } if (strncmp(name, "gl_", 3) == 0) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } programObject->bindAttributeLocation(index, name); @@ -153,12 +168,12 @@ void __stdcall 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)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (target) @@ -187,8 +202,10 @@ void __stdcall glBindBuffer(GLenum target, GLuint buffer) case GL_TRANSFORM_FEEDBACK_BUFFER: context->bindGenericTransformFeedbackBuffer(buffer); return; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -197,15 +214,15 @@ void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer) { EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer); - if (!gl::ValidFramebufferTarget(target)) - { - return gl::error(GL_INVALID_ENUM); - } - 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); @@ -222,15 +239,15 @@ void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer) { EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer); - if (target != GL_RENDERBUFFER) - { - return gl::error(GL_INVALID_ENUM); - } - gl::Context *context = gl::getNonLostContext(); - if (context) { + if (target != GL_RENDERBUFFER) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + context->bindRenderbuffer(renderbuffer); } } @@ -240,41 +257,37 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } switch (target) { case GL_TEXTURE_2D: - context->bindTexture2D(texture); - return; case GL_TEXTURE_CUBE_MAP: - context->bindTextureCubeMap(texture); - return; + break; + case GL_TEXTURE_3D: - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_ENUM); - } - context->bindTexture3D(texture); - return; case GL_TEXTURE_2D_ARRAY: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - context->bindTexture2DArray(texture); - return; + break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } + + context->bindTexture(target, texture); } } @@ -301,35 +314,36 @@ void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha); gl::Context *context = gl::getNonLostContext(); - - switch (modeRGB) + if (context) { - case GL_FUNC_ADD: - case GL_FUNC_SUBTRACT: - case GL_FUNC_REVERSE_SUBTRACT: - case GL_MIN: - case GL_MAX: - break; + switch (modeRGB) + { + case GL_FUNC_ADD: + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + case GL_MIN: + case GL_MAX: + break; - default: - return gl::error(GL_INVALID_ENUM); - } + 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; + switch (modeAlpha) + { + case GL_FUNC_ADD: + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + case GL_MIN: + case GL_MAX: + break; - default: - return gl::error(GL_INVALID_ENUM); - } + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } - if (context) - { context->getState().setBlendEquation(modeRGB, modeAlpha); } } @@ -345,123 +359,131 @@ void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha srcRGB, dstRGB, srcAlpha, dstAlpha); gl::Context *context = gl::getNonLostContext(); - - switch (srcRGB) - { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - case GL_SRC_ALPHA_SATURATE: - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - switch (dstRGB) + if (context) { - 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 || context->getClientVersion() < 3) + switch (srcRGB) { - return gl::error(GL_INVALID_ENUM); + 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; } - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - switch (srcAlpha) - { - case GL_ZERO: - case GL_ONE: - case GL_SRC_COLOR: - case GL_ONE_MINUS_SRC_COLOR: - case GL_DST_COLOR: - case GL_ONE_MINUS_DST_COLOR: - case GL_SRC_ALPHA: - case GL_ONE_MINUS_SRC_ALPHA: - case GL_DST_ALPHA: - case GL_ONE_MINUS_DST_ALPHA: - case GL_CONSTANT_COLOR: - case GL_ONE_MINUS_CONSTANT_COLOR: - case GL_CONSTANT_ALPHA: - case GL_ONE_MINUS_CONSTANT_ALPHA: - case GL_SRC_ALPHA_SATURATE: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + switch (dstRGB) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + break; - 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; - case GL_SRC_ALPHA_SATURATE: - if (!context || context->getClientVersion() < 3) + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + + switch (srcAlpha) { - return gl::error(GL_INVALID_ENUM); + 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; } - break; - default: - return gl::error(GL_INVALID_ENUM); - } + switch (dstAlpha) + { + case GL_ZERO: + case GL_ONE: + case GL_SRC_COLOR: + case GL_ONE_MINUS_SRC_COLOR: + case GL_DST_COLOR: + case GL_ONE_MINUS_DST_COLOR: + case GL_SRC_ALPHA: + case GL_ONE_MINUS_SRC_ALPHA: + case GL_DST_ALPHA: + case GL_ONE_MINUS_DST_ALPHA: + case GL_CONSTANT_COLOR: + case GL_ONE_MINUS_CONSTANT_COLOR: + case GL_CONSTANT_ALPHA: + case GL_ONE_MINUS_CONSTANT_ALPHA: + break; - bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR || - dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR); + case GL_SRC_ALPHA_SATURATE: + if (context->getClientVersion() < 3) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } + break; - bool constantAlphaUsed = (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA || - dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA); + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } - if (constantColorUsed && constantAlphaUsed) - { - ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL"); - return gl::error(GL_INVALID_OPERATION); - } + 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; + } - if (context) - { context->getState().setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha); } } @@ -471,51 +493,60 @@ void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)", target, size, data, usage); - if (size < 0) - { - return gl::error(GL_INVALID_VALUE); - } - gl::Context *context = gl::getNonLostContext(); - - switch (usage) + if (context) { - 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 && context->getClientVersion() < 3) + if (size < 0) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - break; - default: - return gl::error(GL_INVALID_ENUM); - } + 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 (context) - { if (!gl::ValidBufferTarget(context, target)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } gl::Buffer *buffer = context->getState().getTargetBuffer(target); if (!buffer) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - buffer->bufferData(data, size, usage); + gl::Error error = buffer->bufferData(data, size, usage); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -524,49 +555,59 @@ void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)", target, offset, size, data); - if (size < 0 || offset < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - if (data == NULL) - { - return; - } - 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)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } gl::Buffer *buffer = context->getState().getTargetBuffer(target); if (!buffer) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (buffer->isMapped()) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } // Check for possible overflow of size + offset if (!rx::IsUnsignedAdditionSafe(size, offset)) { - return gl::error(GL_OUT_OF_MEMORY); + context->recordError(gl::Error(GL_OUT_OF_MEMORY)); + return; } if (size + offset > buffer->getSize()) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - buffer->bufferSubData(data, size, offset); + gl::Error error = buffer->bufferSubData(data, size, offset); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -574,15 +615,15 @@ GLenum __stdcall glCheckFramebufferStatus(GLenum target) { EVENT("(GLenum target = 0x%X)", target); - if (!gl::ValidFramebufferTarget(target)) - { - return gl::error(GL_INVALID_ENUM, 0); - } - 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(); @@ -596,22 +637,28 @@ void __stdcall glClear(GLbitfield mask) EVENT("(GLbitfield mask = 0x%X)", mask); gl::Context *context = gl::getNonLostContext(); - if (context) { gl::Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); + context->recordError(gl::Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return; } if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - context->clear(mask); + gl::Error error = context->clear(mask); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -621,7 +668,6 @@ void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp red, green, blue, alpha); gl::Context *context = gl::getNonLostContext(); - if (context) { context->getState().setClearColor(red, green, blue, alpha); @@ -633,7 +679,6 @@ void __stdcall glClearDepthf(GLclampf depth) EVENT("(GLclampf depth = %f)", depth); gl::Context *context = gl::getNonLostContext(); - if (context) { context->getState().setClearDepth(depth); @@ -645,7 +690,6 @@ void __stdcall glClearStencil(GLint s) EVENT("(GLint s = %d)", s); gl::Context *context = gl::getNonLostContext(); - if (context) { context->getState().setClearStencil(s); @@ -658,7 +702,6 @@ void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboo 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); @@ -670,7 +713,6 @@ void __stdcall glCompileShader(GLuint shader) EVENT("(GLuint shader = %d)", shader); gl::Context *context = gl::getNonLostContext(); - if (context) { gl::Shader *shaderObject = context->getShader(shader); @@ -679,11 +721,13 @@ void __stdcall glCompileShader(GLuint shader) { if (context->getProgram(shader)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } @@ -699,7 +743,6 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna target, level, internalformat, width, height, border, imageSize, data); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3 && @@ -716,9 +759,11 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna return; } - if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(internalformat, GL_UNSIGNED_BYTE, width, height)) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + if (imageSize < 0 || static_cast(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } switch (target) @@ -743,7 +788,8 @@ void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum interna break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -757,7 +803,6 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs target, level, xoffset, yoffset, width, height, format, imageSize, data); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3 && @@ -774,9 +819,11 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs return; } - if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(format, GL_UNSIGNED_BYTE, width, height)) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); + if (imageSize < 0 || static_cast(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } switch (target) @@ -801,7 +848,8 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -813,7 +861,6 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma target, level, internalformat, x, y, width, height, border); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3 && @@ -853,8 +900,9 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma } break; - default: - return gl::error(GL_INVALID_ENUM); + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -866,7 +914,6 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL target, level, xoffset, yoffset, x, y, width, height); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3 && @@ -907,7 +954,8 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -930,7 +978,6 @@ GLuint __stdcall glCreateShader(GLenum type) EVENT("(GLenum type = 0x%X)", type); gl::Context *context = gl::getNonLostContext(); - if (context) { switch (type) @@ -938,8 +985,10 @@ GLuint __stdcall glCreateShader(GLenum type) case GL_FRAGMENT_SHADER: case GL_VERTEX_SHADER: return context->createShader(type); + default: - return gl::error(GL_INVALID_ENUM, 0); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return 0; } } @@ -950,22 +999,22 @@ void __stdcall glCullFace(GLenum mode) { EVENT("(GLenum mode = 0x%X)", mode); - switch (mode) + gl::Context *context = gl::getNonLostContext(); + if (context) { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: + switch (mode) { - gl::Context *context = gl::getNonLostContext(); + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; - if (context) - { - context->getState().setCullMode(mode); - } + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - break; - default: - return gl::error(GL_INVALID_ENUM); + + context->getState().setCullMode(mode); } } @@ -973,15 +1022,15 @@ void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers) { EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers); - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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]); @@ -993,15 +1042,15 @@ void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences) { EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences); - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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]); @@ -1013,15 +1062,15 @@ void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) { EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers); - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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) @@ -1036,24 +1085,25 @@ void __stdcall glDeleteProgram(GLuint program) { EVENT("(GLuint program = %d)", program); - if (program == 0) - { - return; - } - gl::Context *context = gl::getNonLostContext(); - if (context) { + if (program == 0) + { + return; + } + if (!context->getProgram(program)) { if(context->getShader(program)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } @@ -1065,15 +1115,15 @@ void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids) { EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids); - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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]); @@ -1085,15 +1135,15 @@ void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) { EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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]); @@ -1105,24 +1155,25 @@ void __stdcall glDeleteShader(GLuint shader) { EVENT("(GLuint shader = %d)", shader); - if (shader == 0) - { - return; - } - gl::Context *context = gl::getNonLostContext(); - if (context) { + if (shader == 0) + { + return; + } + if (!context->getShader(shader)) { if(context->getProgram(shader)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } @@ -1134,15 +1185,15 @@ void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures) { EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures); - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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) @@ -1157,26 +1208,26 @@ void __stdcall glDepthFunc(GLenum func) { EVENT("(GLenum func = 0x%X)", func); - switch (func) - { - case GL_NEVER: - case GL_ALWAYS: - case GL_LESS: - case GL_LEQUAL: - case GL_EQUAL: - case GL_GREATER: - case GL_GEQUAL: - case GL_NOTEQUAL: - break; - default: - return gl::error(GL_INVALID_ENUM); - } - gl::Context *context = gl::getNonLostContext(); - if (context) { - context->getState().setDepthFunc(func); + 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; + } } } @@ -1185,7 +1236,6 @@ void __stdcall glDepthMask(GLboolean flag) EVENT("(GLboolean flag = %u)", flag); gl::Context *context = gl::getNonLostContext(); - if (context) { context->getState().setDepthMask(flag != GL_FALSE); @@ -1197,7 +1247,6 @@ void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar) EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar); gl::Context *context = gl::getNonLostContext(); - if (context) { context->getState().setDepthRange(zNear, zFar); @@ -1209,10 +1258,8 @@ void __stdcall 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); @@ -1222,11 +1269,13 @@ void __stdcall glDetachShader(GLuint program, GLuint shader) shaderByProgramHandle = context->getShader(program); if (!shaderByProgramHandle) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } else { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } } @@ -1235,17 +1284,20 @@ void __stdcall glDetachShader(GLuint program, GLuint shader) gl::Program *programByShaderHandle = context->getProgram(shader); if (!programByShaderHandle) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } else { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } } if (!programObject->detachShader(shaderObject)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } } } @@ -1255,12 +1307,12 @@ void __stdcall glDisable(GLenum cap) EVENT("(GLenum cap = 0x%X)", cap); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidCap(context, cap)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } context->getState().setEnableFeature(cap, false); @@ -1271,15 +1323,15 @@ void __stdcall glDisableVertexAttribArray(GLuint index) { EVENT("(GLuint index = %d)", index); - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - 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); } } @@ -1289,15 +1341,19 @@ void __stdcall 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)) + if (!ValidateDrawArrays(context, mode, first, count, 0)) { return; } - context->drawArrays(mode, first, count, 0); + gl::Error error = context->drawArrays(mode, first, count, 0); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -1306,15 +1362,19 @@ void __stdcall glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei coun 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 (!ValidateDrawArraysInstanced(context, mode, first, count, primcount)) + if (!ValidateDrawArraysInstancedANGLE(context, mode, first, count, primcount)) { return; } - context->drawArrays(mode, first, count, primcount); + gl::Error error = context->drawArrays(mode, first, count, primcount); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -1324,15 +1384,20 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv mode, count, type, indices); gl::Context *context = gl::getNonLostContext(); - if (context) { - if (!ValidateDrawElements(context, mode, count, type, indices)) + rx::RangeUI indexRange; + if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange)) { return; } - context->drawElements(mode, count, type, indices, 0); + gl::Error error = context->drawElements(mode, count, type, indices, 0, indexRange); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -1342,15 +1407,20 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t mode, count, type, indices, primcount); gl::Context *context = gl::getNonLostContext(); - if (context) { - if (!ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount)) + rx::RangeUI indexRange; + if (!ValidateDrawElementsInstancedANGLE(context, mode, count, type, indices, primcount, &indexRange)) { return; } - context->drawElements(mode, count, type, indices, primcount); + gl::Error error = context->drawElements(mode, count, type, indices, primcount, indexRange); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -1359,12 +1429,12 @@ void __stdcall glEnable(GLenum cap) EVENT("(GLenum cap = 0x%X)", cap); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidCap(context, cap)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } context->getState().setEnableFeature(cap, true); @@ -1375,15 +1445,15 @@ void __stdcall glEnableVertexAttribArray(GLuint index) { EVENT("(GLuint index = %d)", index); - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - 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); } } @@ -1393,7 +1463,6 @@ void __stdcall glEndQueryEXT(GLenum target) EVENT("GLenum target = 0x%X)", target); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateEndQuery(context, target)) @@ -1401,7 +1470,12 @@ void __stdcall glEndQueryEXT(GLenum target) return; } - context->endQuery(target); + gl::Error error = context->endQuery(target); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -1410,19 +1484,20 @@ void __stdcall glFinishFenceNV(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::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (fenceObject->isFence() != GL_TRUE) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } fenceObject->finishFence(); @@ -1434,7 +1509,6 @@ void __stdcall glFinish(void) EVENT("()"); gl::Context *context = gl::getNonLostContext(); - if (context) { context->sync(true); @@ -1446,7 +1520,6 @@ void __stdcall glFlush(void) EVENT("()"); gl::Context *context = gl::getNonLostContext(); - if (context) { context->sync(false); @@ -1458,15 +1531,15 @@ void __stdcall glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenu EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, " "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer); - if (!gl::ValidFramebufferTarget(target) || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)) - { - return gl::error(GL_INVALID_ENUM); - } - 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; @@ -1542,21 +1615,19 @@ void __stdcall glFrontFace(GLenum mode) { EVENT("(GLenum mode = 0x%X)", mode); - switch (mode) + gl::Context *context = gl::getNonLostContext(); + if (context) { - case GL_CW: - case GL_CCW: + switch (mode) { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->getState().setFrontFace(mode); - } + case GL_CW: + case GL_CCW: + context->getState().setFrontFace(mode); + break; + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - break; - default: - return gl::error(GL_INVALID_ENUM); } } @@ -1564,15 +1635,15 @@ void __stdcall glGenBuffers(GLsizei n, GLuint* buffers) { EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers); - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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(); @@ -1585,23 +1656,25 @@ void __stdcall glGenerateMipmap(GLenum target) EVENT("(GLenum target = 0x%X)", target); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidTextureTarget(context, target)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } gl::Texture *texture = context->getTargetTexture(target); if (texture == NULL) { - return gl::error(GL_INVALID_OPERATION); + 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 @@ -1615,23 +1688,26 @@ void __stdcall glGenerateMipmap(GLenum target) internalFormat == GL_LUMINANCE8_ALPHA8_EXT || internalFormat == GL_ALPHA8_EXT; - if (gl::GetDepthBits(internalFormat) > 0 || gl::GetStencilBits(internalFormat) > 0 || !formatCaps.filterable || - (!formatCaps.renderable && !isLUMA) || gl::IsFormatCompressed(internalFormat)) + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0 || !formatCaps.filterable || + (!formatCaps.renderable && !isLUMA) || formatInfo.compressed) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } // GL_EXT_sRGB does not support mipmap generation on sRGB textures - if (context->getClientVersion() == 2 && gl::GetColorEncoding(internalFormat) == GL_SRGB) + if (context->getClientVersion() == 2 && formatInfo.colorEncoding == GL_SRGB) { - return gl::error(GL_INVALID_OPERATION); + 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)); - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } // Cube completeness check @@ -1640,7 +1716,8 @@ void __stdcall glGenerateMipmap(GLenum target) gl::TextureCubeMap *textureCube = static_cast(texture); if (!textureCube->isCubeComplete()) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } } @@ -1652,15 +1729,15 @@ void __stdcall glGenFencesNV(GLsizei n, GLuint* fences) { EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences); - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } - gl::Context *context = gl::getNonLostContext(); + if (context) + { + if (n < 0) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } - if (context) - { for (int i = 0; i < n; i++) { fences[i] = context->createFenceNV(); @@ -1672,15 +1749,15 @@ void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers) { EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers); - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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(); @@ -1693,12 +1770,12 @@ void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids) EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); gl::Context *context = gl::getNonLostContext(); - if (context) { if (n < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } for (GLsizei i = 0; i < n; i++) @@ -1712,15 +1789,15 @@ void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) { EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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(); @@ -1732,15 +1809,15 @@ void __stdcall glGenTextures(GLsizei n, GLuint* textures) { EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures); - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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(); @@ -1754,32 +1831,35 @@ void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)", program, index, bufsize, length, size, type, name); - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } if (index >= (GLuint)programObject->getActiveAttributeCount()) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } programObject->getActiveAttribute(index, bufsize, length, size, type, name); @@ -1792,32 +1872,36 @@ void __stdcall glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, "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); - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } 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)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } if (index >= (GLuint)programObject->getActiveUniformCount()) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } programObject->getActiveUniform(index, bufsize, length, size, type, name); @@ -1829,26 +1913,28 @@ void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* c EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)", program, maxcount, count, shaders); - if (maxcount < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } @@ -1856,33 +1942,34 @@ void __stdcall glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* c } } -int __stdcall glGetAttribLocation(GLuint program, const GLchar* name) +GLint __stdcall 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)) { - return gl::error(GL_INVALID_OPERATION, -1); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return -1; } else { - return gl::error(GL_INVALID_VALUE, -1); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return -1; } } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programObject->isLinked() || !programBinary) { - return gl::error(GL_INVALID_OPERATION, -1); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return -1; } return programBinary->getAttributeLocation(name); @@ -1896,7 +1983,6 @@ void __stdcall 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; @@ -1922,17 +2008,18 @@ void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!gl::ValidBufferTarget(context, target)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } if (!gl::ValidBufferParameter(context, pname)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } gl::Buffer *buffer = context->getState().getTargetBuffer(target); @@ -1940,7 +2027,8 @@ void __stdcall glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params if (!buffer) { // A null buffer means that "0" is bound to the requested buffer target - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } switch (pname) @@ -1986,21 +2074,21 @@ void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) { EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params); - gl::Context *context = gl::getNonLostContext(); - if (context) { gl::FenceNV *fenceObject = context->getFenceNV(fence); if (fenceObject == NULL) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (fenceObject->isFence() != GL_TRUE) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } switch (pname) @@ -2009,7 +2097,9 @@ void __stdcall glGetFenceivNV(GLuint fence, GLenum pname, GLint *params) case GL_FENCE_CONDITION_NV: break; - default: return gl::error(GL_INVALID_ENUM); + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } params[0] = fenceObject->getFencei(pname); @@ -2021,7 +2111,6 @@ void __stdcall 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; @@ -2048,12 +2137,12 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac target, attachment, pname, params); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!gl::ValidFramebufferTarget(target)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } int clientVersion = context->getClientVersion(); @@ -2065,12 +2154,15 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac 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) { - return gl::error(GL_INVALID_ENUM); + 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: @@ -2081,11 +2173,14 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: if (clientVersion < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } // Determine if the attachment is a valid enum @@ -2098,7 +2193,8 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac case GL_DEPTH_STENCIL_ATTACHMENT: if (clientVersion < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } break; @@ -2110,7 +2206,8 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac if (attachment < GL_COLOR_ATTACHMENT0_EXT || (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } break; } @@ -2122,7 +2219,8 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac { if (clientVersion < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } switch (attachment) @@ -2131,8 +2229,10 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac case GL_DEPTH: case GL_STENCIL: break; + default: - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } } else @@ -2148,14 +2248,18 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac case GL_DEPTH_ATTACHMENT: case GL_STENCIL_ATTACHMENT: break; + case GL_DEPTH_STENCIL_ATTACHMENT: if (framebuffer->hasValidDepthStencil()) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } break; + default: - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } } } @@ -2212,7 +2316,8 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: if (clientVersion < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = 0; break; @@ -2220,11 +2325,13 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac default: if (clientVersion < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } else { - gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } } } @@ -2243,7 +2350,8 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: if (attachmentObjectType != GL_RENDERBUFFER && attachmentObjectType != GL_TEXTURE) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = attachmentHandle; break; @@ -2251,7 +2359,8 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: if (attachmentObjectType != GL_TEXTURE) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = attachmentLevel; break; @@ -2259,7 +2368,8 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: if (attachmentObjectType != GL_TEXTURE) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = gl::IsCubemapTextureTarget(attachmentType) ? attachmentType : 0; break; @@ -2289,9 +2399,10 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac break; case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: - if (attachment == GL_DEPTH_STENCIL) + if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) { - gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } *params = attachmentObject->getComponentType(); break; @@ -2303,7 +2414,8 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: if (attachmentObjectType != GL_TEXTURE) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = attachmentLayer; break; @@ -2335,7 +2447,6 @@ void __stdcall 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; @@ -2362,14 +2473,14 @@ void __stdcall 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) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } if (context->getClientVersion() < 3) @@ -2381,7 +2492,8 @@ void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params) case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: case GL_TRANSFORM_FEEDBACK_VARYINGS: case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } @@ -2432,8 +2544,10 @@ void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params) case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: *params = programObject->getTransformFeedbackVaryingMaxLength(); break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -2443,20 +2557,21 @@ void __stdcall glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* len EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", program, bufsize, length, infolog); - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } programObject->getInfoLog(bufsize, length, infolog); @@ -2468,12 +2583,12 @@ void __stdcall 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)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (pname) @@ -2483,7 +2598,8 @@ void __stdcall glGetQueryivEXT(GLenum target, GLenum pname, GLint *params) break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -2493,31 +2609,49 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (context->getState().getActiveQueryId(queryObject->getType()) == id) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } switch(pname) { case GL_QUERY_RESULT_EXT: - params[0] = queryObject->getResult(); + { + gl::Error error = queryObject->getResult(params); + if (error.isError()) + { + context->recordError(error); + return; + } + } break; + case GL_QUERY_RESULT_AVAILABLE_EXT: - params[0] = queryObject->isResultAvailable(); + { + gl::Error error = queryObject->isResultAvailable(params); + if (error.isError()) + { + context->recordError(error); + return; + } + } break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -2527,17 +2661,18 @@ void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* 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) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } if (context->getState().getRenderbufferId() == 0) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getState().getRenderbufferId()); @@ -2553,15 +2688,19 @@ void __stdcall glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* 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) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = renderbuffer->getSamples(); break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -2571,14 +2710,14 @@ void __stdcall 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) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } switch (pname) @@ -2601,8 +2740,10 @@ void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params) case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE: *params = shaderObject->getTranslatedSourceLength(); return; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -2612,20 +2753,21 @@ void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* lengt EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)", shader, bufsize, length, infolog); - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } shaderObject->getInfoLog(bufsize, length, infolog); @@ -2637,36 +2779,45 @@ void __stdcall glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontyp EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)", shadertype, precisiontype, range, precision); - switch (shadertype) + gl::Context *context = gl::getNonLostContext(); + if (context) { - case GL_VERTEX_SHADER: - case GL_FRAGMENT_SHADER: - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - switch (precisiontype) - { - case GL_LOW_FLOAT: - case GL_MEDIUM_FLOAT: - case GL_HIGH_FLOAT: - // Assume IEEE 754 precision - range[0] = 127; - range[1] = 127; - *precision = 23; - break; - case GL_LOW_INT: - case GL_MEDIUM_INT: - case GL_HIGH_INT: - // Some (most) hardware only supports single-precision floating-point numbers, - // which can accurately represent integers up to +/-16777216 - range[0] = 24; - range[1] = 24; - *precision = 0; - break; - default: - return gl::error(GL_INVALID_ENUM); + 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; + } } } @@ -2675,20 +2826,21 @@ void __stdcall glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", shader, bufsize, length, source); - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } shaderObject->getSource(bufsize, length, source); @@ -2700,20 +2852,21 @@ void __stdcall glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)", shader, bufsize, length, source); - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } shaderObject->getTranslatedSource(bufsize, length, source); @@ -2730,8 +2883,10 @@ const GLubyte* __stdcall glGetString(GLenum 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) { @@ -2741,6 +2896,7 @@ const GLubyte* __stdcall glGetString(GLenum name) { return (GLubyte*)"OpenGL ES 3.0 (ANGLE " ANGLE_VERSION_STRING ")"; } + case GL_SHADING_LANGUAGE_VERSION: if (context->getClientVersion() == 2) { @@ -2750,10 +2906,16 @@ const GLubyte* __stdcall glGetString(GLenum name) { return (GLubyte*)"OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")"; } + case GL_EXTENSIONS: return (GLubyte*)((context != NULL) ? context->getExtensionString().c_str() : ""); + default: - return gl::error(GL_INVALID_ENUM, (GLubyte*)NULL); + if (context) + { + context->recordError(gl::Error(GL_INVALID_ENUM)); + } + return NULL; } } @@ -2762,14 +2924,14 @@ void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params); gl::Context *context = gl::getNonLostContext(); - if (context) { gl::Texture *texture = context->getTargetTexture(target); if (!texture) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (pname) @@ -2789,7 +2951,8 @@ void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) case GL_TEXTURE_WRAP_R: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = (GLfloat)texture->getSamplerState().wrapR; break; @@ -2800,7 +2963,8 @@ void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) case GL_TEXTURE_IMMUTABLE_LEVELS: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = (GLfloat)texture->immutableLevelCount(); break; @@ -2810,68 +2974,79 @@ void __stdcall glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params) case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (!context->getExtensions().textureFilterAnisotropic) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = (GLfloat)texture->getSamplerState().maxAnisotropy; break; case GL_TEXTURE_SWIZZLE_R: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = (GLfloat)texture->getSamplerState().swizzleRed; break; case GL_TEXTURE_SWIZZLE_G: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = (GLfloat)texture->getSamplerState().swizzleGreen; break; case GL_TEXTURE_SWIZZLE_B: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = (GLfloat)texture->getSamplerState().swizzleBlue; break; case GL_TEXTURE_SWIZZLE_A: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = (GLfloat)texture->getSamplerState().swizzleAlpha; break; case GL_TEXTURE_BASE_LEVEL: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = (GLfloat)texture->getSamplerState().baseLevel; break; case GL_TEXTURE_MAX_LEVEL: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = (GLfloat)texture->getSamplerState().maxLevel; break; case GL_TEXTURE_MIN_LOD: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = texture->getSamplerState().minLod; break; case GL_TEXTURE_MAX_LOD: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = texture->getSamplerState().maxLod; break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -2881,14 +3056,14 @@ void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); gl::Context *context = gl::getNonLostContext(); - if (context) { gl::Texture *texture = context->getTargetTexture(target); if (!texture) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (pname) @@ -2908,7 +3083,8 @@ void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) case GL_TEXTURE_WRAP_R: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = texture->getSamplerState().wrapR; break; @@ -2919,7 +3095,8 @@ void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) case GL_TEXTURE_IMMUTABLE_LEVELS: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = texture->immutableLevelCount(); break; @@ -2929,68 +3106,79 @@ void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (!context->getExtensions().textureFilterAnisotropic) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = (GLint)texture->getSamplerState().maxAnisotropy; break; case GL_TEXTURE_SWIZZLE_R: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = texture->getSamplerState().swizzleRed; break; case GL_TEXTURE_SWIZZLE_G: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = texture->getSamplerState().swizzleGreen; break; case GL_TEXTURE_SWIZZLE_B: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = texture->getSamplerState().swizzleBlue; break; case GL_TEXTURE_SWIZZLE_A: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = texture->getSamplerState().swizzleAlpha; break; case GL_TEXTURE_BASE_LEVEL: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = texture->getSamplerState().baseLevel; break; case GL_TEXTURE_MAX_LEVEL: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = texture->getSamplerState().maxLevel; break; case GL_TEXTURE_MIN_LOD: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = (GLint)texture->getSamplerState().minLod; break; case GL_TEXTURE_MAX_LOD: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *params = (GLint)texture->getSamplerState().maxLod; break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -3000,37 +3188,20 @@ void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSiz EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)", program, location, bufSize, params); - if (bufSize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - gl::Context *context = gl::getNonLostContext(); - if (context) { - if (program == 0) + if (!ValidateGetnUniformfvEXT(context, program, location, bufSize, params)) { - return gl::error(GL_INVALID_VALUE); + return; } gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } - + ASSERT(programObject); gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + ASSERT(programBinary); - if (!programBinary->getUniformfv(location, &bufSize, params)) - { - return gl::error(GL_INVALID_OPERATION); - } + programBinary->getUniformfv(location, params); } } @@ -3039,31 +3210,19 @@ void __stdcall 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 (program == 0) + if (!ValidateGetUniformfv(context, program, location, params)) { - return gl::error(GL_INVALID_VALUE); + return; } gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } - + ASSERT(programObject); gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + ASSERT(programBinary); - if (!programBinary->getUniformfv(location, NULL, params)) - { - return gl::error(GL_INVALID_OPERATION); - } + programBinary->getUniformfv(location, params); } } @@ -3072,37 +3231,20 @@ void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSiz EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)", program, location, bufSize, params); - if (bufSize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - gl::Context *context = gl::getNonLostContext(); - if (context) { - if (program == 0) + if (!ValidateGetnUniformivEXT(context, program, location, bufSize, params)) { - return gl::error(GL_INVALID_VALUE); + return; } gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } - + ASSERT(programObject); gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + ASSERT(programBinary); - if (!programBinary->getUniformiv(location, &bufSize, params)) - { - return gl::error(GL_INVALID_OPERATION); - } + programBinary->getUniformiv(location, params); } } @@ -3111,65 +3253,55 @@ void __stdcall 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 (program == 0) + if (!ValidateGetUniformiv(context, program, location, params)) { - return gl::error(GL_INVALID_VALUE); + return; } gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } - + ASSERT(programObject); gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + ASSERT(programBinary); - if (!programBinary->getUniformiv(location, NULL, params)) - { - return gl::error(GL_INVALID_OPERATION); - } + programBinary->getUniformiv(location, params); } } -int __stdcall glGetUniformLocation(GLuint program, const GLchar* name) +GLint __stdcall glGetUniformLocation(GLuint program, const GLchar* name) { EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name); gl::Context *context = gl::getNonLostContext(); - - if (strstr(name, "gl_") == name) - { - return -1; - } - if (context) { + if (strstr(name, "gl_") == name) + { + return -1; + } + gl::Program *programObject = context->getProgram(program); if (!programObject) { if (context->getShader(program)) { - return gl::error(GL_INVALID_OPERATION, -1); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return -1; } else { - return gl::error(GL_INVALID_VALUE, -1); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return -1; } } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programObject->isLinked() || !programBinary) { - return gl::error(GL_INVALID_OPERATION, -1); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return -1; } return programBinary->getUniformLocation(name); @@ -3183,16 +3315,16 @@ void __stdcall glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params) EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params); gl::Context *context = gl::getNonLostContext(); - if (context) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion())) + if (!gl::ValidateGetVertexAttribParameters(context, pname)) { return; } @@ -3217,17 +3349,17 @@ void __stdcall glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params) EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params); gl::Context *context = gl::getNonLostContext(); - if (context) { if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion())) + if (!gl::ValidateGetVertexAttribParameters(context, pname)) { return; } @@ -3253,17 +3385,18 @@ void __stdcall glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** po 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) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } *pointer = const_cast(context->getState().getVertexAttribPointer(index)); @@ -3274,27 +3407,35 @@ void __stdcall glHint(GLenum target, GLenum mode) { EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode); - switch (mode) - { - case GL_FASTEST: - case GL_NICEST: - case GL_DONT_CARE: - break; - default: - return gl::error(GL_INVALID_ENUM); - } - gl::Context *context = gl::getNonLostContext(); - switch (target) + if (context) { - case GL_GENERATE_MIPMAP_HINT: - if (context) context->getState().setGenerateMipmapHint(mode); - break; - case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: - if (context) context->getState().setFragmentShaderDerivativeHint(mode); - break; - default: - return gl::error(GL_INVALID_ENUM); + 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; + } } } @@ -3303,7 +3444,6 @@ GLboolean __stdcall glIsBuffer(GLuint buffer) EVENT("(GLuint buffer = %d)", buffer); gl::Context *context = gl::getNonLostContext(); - if (context && buffer) { gl::Buffer *bufferObject = context->getBuffer(buffer); @@ -3322,12 +3462,12 @@ GLboolean __stdcall glIsEnabled(GLenum cap) EVENT("(GLenum cap = 0x%X)", cap); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidCap(context, cap)) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return GL_FALSE; } return context->getState().getEnableFeature(cap); @@ -3341,7 +3481,6 @@ GLboolean __stdcall glIsFenceNV(GLuint fence) EVENT("(GLuint fence = %d)", fence); gl::Context *context = gl::getNonLostContext(); - if (context) { gl::FenceNV *fenceObject = context->getFenceNV(fence); @@ -3362,7 +3501,6 @@ GLboolean __stdcall glIsFramebuffer(GLuint framebuffer) EVENT("(GLuint framebuffer = %d)", framebuffer); gl::Context *context = gl::getNonLostContext(); - if (context && framebuffer) { gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer); @@ -3381,7 +3519,6 @@ GLboolean __stdcall glIsProgram(GLuint program) EVENT("(GLuint program = %d)", program); gl::Context *context = gl::getNonLostContext(); - if (context && program) { gl::Program *programObject = context->getProgram(program); @@ -3400,7 +3537,6 @@ GLboolean __stdcall 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; @@ -3414,7 +3550,6 @@ GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer) EVENT("(GLuint renderbuffer = %d)", renderbuffer); gl::Context *context = gl::getNonLostContext(); - if (context && renderbuffer) { gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); @@ -3433,7 +3568,6 @@ GLboolean __stdcall glIsShader(GLuint shader) EVENT("(GLuint shader = %d)", shader); gl::Context *context = gl::getNonLostContext(); - if (context && shader) { gl::Shader *shaderObject = context->getShader(shader); @@ -3452,7 +3586,6 @@ GLboolean __stdcall glIsTexture(GLuint texture) EVENT("(GLuint texture = %d)", texture); gl::Context *context = gl::getNonLostContext(); - if (context && texture) { gl::Texture *textureObject = context->getTexture(texture); @@ -3470,15 +3603,15 @@ void __stdcall glLineWidth(GLfloat width) { EVENT("(GLfloat width = %f)", width); - if (width <= 0.0f) - { - return gl::error(GL_INVALID_VALUE); - } - gl::Context *context = gl::getNonLostContext(); - if (context) { + if (width <= 0.0f) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } + context->getState().setLineWidth(width); } } @@ -3488,7 +3621,6 @@ void __stdcall glLinkProgram(GLuint program) EVENT("(GLuint program = %d)", program); gl::Context *context = gl::getNonLostContext(); - if (context) { gl::Program *programObject = context->getProgram(program); @@ -3497,11 +3629,13 @@ void __stdcall glLinkProgram(GLuint program) { if (context->getShader(program)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } @@ -3514,7 +3648,6 @@ void __stdcall glPixelStorei(GLenum pname, GLint param) EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param); gl::Context *context = gl::getNonLostContext(); - if (context) { switch (pname) @@ -3522,7 +3655,8 @@ void __stdcall glPixelStorei(GLenum pname, GLint param) case GL_UNPACK_ALIGNMENT: if (param != 1 && param != 2 && param != 4 && param != 8) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } context->getState().setUnpackAlignment(param); @@ -3531,7 +3665,8 @@ void __stdcall glPixelStorei(GLenum pname, GLint param) case GL_PACK_ALIGNMENT: if (param != 1 && param != 2 && param != 4 && param != 8) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } context->getState().setPackAlignment(param); @@ -3551,13 +3686,15 @@ void __stdcall glPixelStorei(GLenum pname, GLint param) case GL_PACK_SKIP_PIXELS: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } UNIMPLEMENTED(); break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -3567,7 +3704,6 @@ void __stdcall 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); @@ -3582,22 +3718,27 @@ void __stdcall glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, "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); - if (width < 0 || height < 0 || bufSize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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; } - context->readPixels(x, y, width, height, format, type, &bufSize, data); + gl::Error error = context->readPixels(x, y, width, height, format, type, &bufSize, data); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -3608,22 +3749,27 @@ void __stdcall glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)", x, y, width, height, format, type, pixels); - if (width < 0 || height < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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; } - context->readPixels(x, y, width, height, format, type, NULL, pixels); + gl::Error error = context->readPixels(x, y, width, height, format, type, NULL, pixels); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -3631,7 +3777,12 @@ void __stdcall glReleaseShaderCompiler(void) { EVENT("()"); - gl::Shader::releaseCompiler(); + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + context->releaseShaderCompiler(); + } } void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) @@ -3640,7 +3791,6 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp target, samples, internalformat, width, height); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat, @@ -3674,20 +3824,21 @@ void __stdcall glSetFenceNV(GLuint fence, GLenum condition) { EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition); - if (condition != GL_ALL_COMPLETED_NV) - { - return gl::error(GL_INVALID_ENUM); - } - 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } fenceObject->setFence(condition); @@ -3698,15 +3849,15 @@ void __stdcall glScissor(GLint x, GLint y, GLsizei width, GLsizei height) { EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); - if (width < 0 || height < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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); } } @@ -3717,8 +3868,19 @@ void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryfor "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", n, shaders, binaryformat, binary, length); - // No binary shader formats are supported. - return gl::error(GL_INVALID_ENUM); + 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(); + } } void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length) @@ -3726,26 +3888,28 @@ void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar* const* EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)", shader, count, string, length); - if (count < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } @@ -3762,35 +3926,38 @@ void __stdcall glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint { EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask); - switch (face) + gl::Context *context = gl::getNonLostContext(); + if (context) { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + switch (face) + { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; - switch (func) - { - case GL_NEVER: - case GL_ALWAYS: - case GL_LESS: - case GL_LEQUAL: - case GL_EQUAL: - case GL_GEQUAL: - case GL_GREATER: - case GL_NOTEQUAL: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } - gl::Context *context = gl::getNonLostContext(); + 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 (context) - { if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { context->getState().setStencilParams(func, ref, mask); @@ -3812,20 +3979,21 @@ void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask) { EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask); - switch (face) - { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - break; - default: - return gl::error(GL_INVALID_ENUM); - } - 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); @@ -3848,65 +4016,72 @@ void __stdcall glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenu EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)", face, fail, zfail, zpass); - switch (face) + gl::Context *context = gl::getNonLostContext(); + if (context) { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + switch (face) + { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; - switch (fail) - { - case GL_ZERO: - case GL_KEEP: - case GL_REPLACE: - case GL_INCR: - case GL_DECR: - case GL_INVERT: - case GL_INCR_WRAP: - case GL_DECR_WRAP: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + 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: - return gl::error(GL_INVALID_ENUM); - } + switch (fail) + { + case GL_ZERO: + case GL_KEEP: + case GL_REPLACE: + case GL_INCR: + case GL_DECR: + case GL_INVERT: + case GL_INCR_WRAP: + case GL_DECR_WRAP: + break; - switch (zpass) - { - case GL_ZERO: - case GL_KEEP: - case GL_REPLACE: - case GL_INCR: - case GL_DECR: - case GL_INVERT: - case GL_INCR_WRAP: - case GL_DECR_WRAP: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } - gl::Context *context = gl::getNonLostContext(); + 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 (context) - { if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { context->getState().setStencilOperations(fail, zfail, zpass); @@ -3924,19 +4099,20 @@ GLboolean __stdcall glTestFenceNV(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::error(GL_INVALID_OPERATION, GL_TRUE); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_TRUE; } if (fenceObject->isFence() != GL_TRUE) { - return gl::error(GL_INVALID_OPERATION, GL_TRUE); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_TRUE; } return fenceObject->testFence(); @@ -3953,7 +4129,6 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL target, level, internalformat, width, height, border, format, type, pixels); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3 && @@ -4024,7 +4199,6 @@ void __stdcall 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))) @@ -4036,7 +4210,8 @@ void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param) if (!texture) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (pname) @@ -4073,7 +4248,6 @@ void __stdcall 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)) @@ -4085,7 +4259,8 @@ void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param) if (!texture) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (pname) @@ -4123,12 +4298,12 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf target, levels, internalformat, width, height); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!context->getExtensions().textureStorage) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (context->getClientVersion() < 3 && @@ -4160,7 +4335,8 @@ void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalf break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -4174,7 +4350,6 @@ void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint target, level, xoffset, yoffset, width, height, format, type, pixels); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3 && @@ -4234,7 +4409,6 @@ void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v) EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniform(context, GL_FLOAT, location, count)) @@ -4257,7 +4431,6 @@ void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v) EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniform(context, GL_INT, location, count)) @@ -4282,7 +4455,6 @@ void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v) EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniform(context, GL_FLOAT_VEC2, location, count)) @@ -4307,7 +4479,6 @@ void __stdcall glUniform2iv(GLint location, GLsizei count, const GLint* v) EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniform(context, GL_INT_VEC2, location, count)) @@ -4332,7 +4503,6 @@ void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v) EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniform(context, GL_FLOAT_VEC3, location, count)) @@ -4357,7 +4527,6 @@ void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v) EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniform(context, GL_INT_VEC3, location, count)) @@ -4382,7 +4551,6 @@ void __stdcall glUniform4fv(GLint location, GLsizei count, const GLfloat* v) EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniform(context, GL_FLOAT_VEC4, location, count)) @@ -4407,7 +4575,6 @@ void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v) EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniform(context, GL_INT_VEC4, location, count)) @@ -4426,7 +4593,6 @@ void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean trans location, count, transpose, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose)) @@ -4445,7 +4611,6 @@ void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean trans location, count, transpose, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose)) @@ -4464,7 +4629,6 @@ void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean trans location, count, transpose, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose)) @@ -4482,7 +4646,6 @@ void __stdcall glUseProgram(GLuint program) EVENT("(GLuint program = %d)", program); gl::Context *context = gl::getNonLostContext(); - if (context) { gl::Program *programObject = context->getProgram(program); @@ -4491,17 +4654,20 @@ void __stdcall glUseProgram(GLuint program) { if (context->getShader(program)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } if (program != 0 && !programObject->isLinked()) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } context->useProgram(program); @@ -4513,7 +4679,6 @@ void __stdcall glValidateProgram(GLuint program) EVENT("(GLuint program = %d)", program); gl::Context *context = gl::getNonLostContext(); - if (context) { gl::Program *programObject = context->getProgram(program); @@ -4522,15 +4687,17 @@ void __stdcall glValidateProgram(GLuint program) { if (context->getShader(program)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } - programObject->validate(); + programObject->validate(context->getCaps()); } } @@ -4538,15 +4705,15 @@ void __stdcall glVertexAttrib1f(GLuint index, GLfloat x) { EVENT("(GLuint index = %d, GLfloat x = %f)", index, x); - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - 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); } @@ -4556,15 +4723,15 @@ void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values) { EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - 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); } @@ -4574,15 +4741,15 @@ void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) { EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y); - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - 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); } @@ -4592,15 +4759,15 @@ void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values) { EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - 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); } @@ -4608,17 +4775,17 @@ void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values) void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) { - EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z); - - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } + 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); } @@ -4628,15 +4795,15 @@ void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values) { EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - 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); } @@ -4646,15 +4813,15 @@ void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, G { EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w); - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - 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); } @@ -4664,15 +4831,15 @@ void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values) { EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - 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); } } @@ -4681,15 +4848,15 @@ void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) { EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor); - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - 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); } } @@ -4700,63 +4867,68 @@ void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLbo "GLboolean normalized = %u, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)", index, size, type, normalized, stride, ptr); - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - - if (size < 1 || size > 4) - { - return gl::error(GL_INVALID_VALUE); - } - gl::Context *context = gl::getNonLostContext(); - - switch (type) + if (context) { - 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 && context->getClientVersion() < 3) + if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - else + + 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; } - default: - return gl::error(GL_INVALID_ENUM); - } - if (stride < 0) - { - return gl::error(GL_INVALID_VALUE); - } + 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) - { - return gl::error(GL_INVALID_OPERATION); - } + 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; + } - if (context) - { // [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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, @@ -4768,15 +4940,15 @@ void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height) { EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); - if (width < 0 || height < 0) - { - return gl::error(GL_INVALID_VALUE); - } - 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); } } @@ -4788,12 +4960,12 @@ void __stdcall glReadBuffer(GLenum mode) EVENT("(GLenum mode = 0x%X)", mode); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } // glReadBuffer @@ -4807,12 +4979,12 @@ void __stdcall glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsize "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } // glDrawRangeElements @@ -4828,12 +5000,12 @@ void __stdcall glTexImage3D(GLenum target, GLint level, GLint internalformat, GL target, level, internalformat, width, height, depth, border, format, type, pixels); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } // validateES3TexImageFormat sets the error code if there is an error @@ -4860,7 +5032,8 @@ void __stdcall glTexImage3D(GLenum target, GLint level, GLint internalformat, GL break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -4873,12 +5046,12 @@ void __stdcall glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } // validateES3TexImageFormat sets the error code if there is an error @@ -4912,7 +5085,8 @@ void __stdcall glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -4924,12 +5098,12 @@ void __stdcall glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GL target, level, xoffset, yoffset, zoffset, x, y, width, height); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (!ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset, yoffset, zoffset, @@ -4951,7 +5125,8 @@ void __stdcall glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GL break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer); @@ -4966,17 +5141,19 @@ void __stdcall glCompressedTexImage3D(GLenum target, GLint level, GLenum interna target, level, internalformat, width, height, depth, border, imageSize, data); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(internalformat, GL_UNSIGNED_BYTE, width, height)) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + if (imageSize < 0 || static_cast(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } // validateES3TexImageFormat sets the error code if there is an error @@ -5003,7 +5180,8 @@ void __stdcall glCompressedTexImage3D(GLenum target, GLint level, GLenum interna break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -5016,22 +5194,25 @@ void __stdcall glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffs target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(format, GL_UNSIGNED_BYTE, width, height)) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); + if (imageSize < 0 || static_cast(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height)) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } if (!data) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } // validateES3TexImageFormat sets the error code if there is an error @@ -5065,8 +5246,9 @@ void __stdcall glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffs } break; - default: - return gl::error(GL_INVALID_ENUM); + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -5076,17 +5258,18 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (n < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } for (GLsizei i = 0; i < n; i++) @@ -5101,17 +5284,18 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (n < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } for (GLsizei i = 0; i < n; i++) @@ -5126,12 +5310,12 @@ GLboolean __stdcall glIsQuery(GLuint id) EVENT("(GLuint id = %u)", id); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION, GL_FALSE); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_FALSE; } return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; @@ -5145,19 +5329,25 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (!ValidateBeginQuery(context, target, id)) { return; } - context->beginQuery(target, id); + + gl::Error error = context->beginQuery(target, id); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -5166,12 +5356,12 @@ void __stdcall glEndQuery(GLenum target) EVENT("(GLenum target = 0x%X)", target); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (!ValidateEndQuery(context, target)) @@ -5179,7 +5369,12 @@ void __stdcall glEndQuery(GLenum target) return; } - context->endQuery(target); + gl::Error error = context->endQuery(target); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -5188,17 +5383,18 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (!ValidQueryType(context, target)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (pname) @@ -5208,7 +5404,8 @@ void __stdcall glGetQueryiv(GLenum target, GLenum pname, GLint* params) break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -5218,36 +5415,55 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } gl::Query *queryObject = context->getQuery(id, false, GL_NONE); if (!queryObject) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (context->getState().getActiveQueryId(queryObject->getType()) == id) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } switch(pname) { - case GL_QUERY_RESULT: - params[0] = queryObject->getResult(); + case GL_QUERY_RESULT_EXT: + { + gl::Error error = queryObject->getResult(params); + if (error.isError()) + { + context->recordError(error); + return; + } + } break; - case GL_QUERY_RESULT_AVAILABLE: - params[0] = queryObject->isResultAvailable(); + + case GL_QUERY_RESULT_AVAILABLE_EXT: + { + gl::Error error = queryObject->isResultAvailable(params); + if (error.isError()) + { + context->recordError(error); + return; + } + } break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -5257,12 +5473,12 @@ GLboolean __stdcall glUnmapBuffer(GLenum target) EVENT("(GLenum target = 0x%X)", target); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION, GL_FALSE); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_FALSE; } return glUnmapBufferOES(target); @@ -5276,12 +5492,12 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } glGetBufferPointervOES(target, pname, params); @@ -5291,12 +5507,12 @@ void __stdcall glGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params) void __stdcall glDrawBuffers(GLsizei n, const GLenum* bufs) { gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } glDrawBuffersEXT(n, bufs); @@ -5309,7 +5525,6 @@ void __stdcall glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean tra location, count, transpose, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose)) @@ -5328,7 +5543,6 @@ void __stdcall glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean tra location, count, transpose, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose)) @@ -5347,7 +5561,6 @@ void __stdcall glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean tra location, count, transpose, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose)) @@ -5366,7 +5579,6 @@ void __stdcall glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean tra location, count, transpose, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose)) @@ -5385,7 +5597,6 @@ void __stdcall glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean tra location, count, transpose, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose)) @@ -5404,7 +5615,6 @@ void __stdcall glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean tra location, count, transpose, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose)) @@ -5428,7 +5638,8 @@ void __stdcall glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint sr { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, @@ -5449,12 +5660,12 @@ void __stdcall glRenderbufferStorageMultisample(GLenum target, GLsizei samples, target, samples, internalformat, width, height); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat, @@ -5473,7 +5684,6 @@ void __stdcall glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuin target, attachment, texture, level, layer); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateFramebufferTextureLayer(context, target, attachment, texture, @@ -5511,12 +5721,12 @@ GLvoid* __stdcall glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr le target, offset, length, access); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return NULL; } return glMapBufferRangeEXT(target, offset, length, access); @@ -5530,12 +5740,12 @@ void __stdcall glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeip 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } glFlushMappedBufferRangeEXT(target, offset, length); @@ -5547,12 +5757,12 @@ void __stdcall glBindVertexArray(GLuint array) EVENT("(GLuint array = %u)", array); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } gl::VertexArray *vao = context->getVertexArray(array); @@ -5561,7 +5771,8 @@ void __stdcall glBindVertexArray(GLuint array) { // The default VAO should always exist ASSERT(array != 0); - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } context->bindVertexArray(array); @@ -5573,17 +5784,18 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (n < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) @@ -5601,17 +5813,18 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (n < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) @@ -5626,12 +5839,12 @@ GLboolean __stdcall glIsVertexArray(GLuint array) EVENT("(GLuint array = %u)", array); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION, GL_FALSE); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_FALSE; } if (array == 0) @@ -5653,30 +5866,40 @@ void __stdcall glGetIntegeri_v(GLenum target, GLuint index, GLint* data) target, index, data); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + 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 >= context->getMaxTransformFeedbackBufferBindings()) - return gl::error(GL_INVALID_VALUE); + 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 >= context->getMaximumCombinedUniformBufferBindings()) - return gl::error(GL_INVALID_VALUE); + if (index >= caps.maxCombinedUniformBlocks) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } if (!(context->getIndexedIntegerv(target, index, data))) @@ -5684,10 +5907,15 @@ void __stdcall glGetIntegeri_v(GLenum target, GLuint index, GLint* data) GLenum nativeType; unsigned int numParams = 0; if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) - return gl::error(GL_INVALID_ENUM); + { + 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) { @@ -5718,12 +5946,12 @@ void __stdcall glBeginTransformFeedback(GLenum primitiveMode) EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } switch (primitiveMode) @@ -5732,8 +5960,10 @@ void __stdcall glBeginTransformFeedback(GLenum primitiveMode) case GL_LINES: case GL_POINTS: break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); @@ -5741,7 +5971,8 @@ void __stdcall glBeginTransformFeedback(GLenum primitiveMode) if (transformFeedback->isStarted()) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (transformFeedback->isPaused()) @@ -5760,12 +5991,12 @@ void __stdcall glEndTransformFeedback(void) EVENT("(void)"); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); @@ -5773,7 +6004,8 @@ void __stdcall glEndTransformFeedback(void) if (!transformFeedback->isStarted()) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } transformFeedback->stop(); @@ -5786,37 +6018,42 @@ void __stdcall glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLi target, index, buffer, offset, size); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } + const gl::Caps &caps = context->getCaps(); switch (target) { case GL_TRANSFORM_FEEDBACK_BUFFER: - if (index >= context->getMaxTransformFeedbackBufferBindings()) + if (index >= caps.maxTransformFeedbackSeparateAttributes) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } break; case GL_UNIFORM_BUFFER: - if (index >= context->getMaximumCombinedUniformBufferBindings()) + if (index >= caps.maxUniformBufferBindings) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } if (buffer != 0 && size <= 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } switch (target) @@ -5826,7 +6063,8 @@ void __stdcall glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLi // size and offset must be a multiple of 4 if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0)) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size); @@ -5836,9 +6074,10 @@ void __stdcall glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLi case GL_UNIFORM_BUFFER: // it is an error to bind an offset not a multiple of the alignment - if (buffer != 0 && (offset % context->getUniformBufferOffsetAlignment()) != 0) + if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } context->bindIndexedUniformBuffer(buffer, index, offset, size); @@ -5857,32 +6096,36 @@ void __stdcall glBindBufferBase(GLenum target, GLuint index, GLuint buffer) target, index, buffer); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } + const gl::Caps &caps = context->getCaps(); switch (target) { case GL_TRANSFORM_FEEDBACK_BUFFER: - if (index >= context->getMaxTransformFeedbackBufferBindings()) + if (index >= caps.maxTransformFeedbackSeparateAttributes) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } break; case GL_UNIFORM_BUFFER: - if (index >= context->getMaximumCombinedUniformBufferBindings()) + if (index >= caps.maxUniformBufferBindings) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } switch (target) @@ -5909,31 +6152,35 @@ void __stdcall glTransformFeedbackVaryings(GLuint program, GLsizei count, const program, count, varyings, bufferMode); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (count < 0) { - return gl::error(GL_INVALID_VALUE); + 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) > context->getMaxTransformFeedbackBufferBindings()) + if (static_cast(count) > caps.maxTransformFeedbackSeparateAttributes) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } if (!gl::ValidProgram(context, program)) @@ -5955,17 +6202,18 @@ void __stdcall glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsiz program, index, bufSize, length, size, type, name); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (bufSize < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } if (!gl::ValidProgram(context, program)) @@ -5978,7 +6226,8 @@ void __stdcall glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsiz if (index >= static_cast(programObject->getTransformFeedbackVaryingCount())) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name); @@ -5991,59 +6240,63 @@ void __stdcall glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLs index, size, type, stride, pointer); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - } - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } - if (size < 1 || size > 4) - { - return gl::error(GL_INVALID_VALUE); - } + 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: - return gl::error(GL_INVALID_ENUM); - } + 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; - if (stride < 0) - { - return gl::error(GL_INVALID_VALUE); - } + default: + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; + } - if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4) - { - return gl::error(GL_INVALID_OPERATION); - } + 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; + } - if (context) - { // [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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, false, true, @@ -6057,22 +6310,23 @@ void __stdcall glGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params) index, pname, params); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion())) + if (!gl::ValidateGetVertexAttribParameters(context, pname)) { return; } @@ -6098,22 +6352,23 @@ void __stdcall glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) index, pname, params); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion())) + if (!gl::ValidateGetVertexAttribParameters(context, pname)) { return; } @@ -6139,17 +6394,18 @@ void __stdcall glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint index, x, y, z, w); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } GLint vals[4] = { x, y, z, w }; @@ -6163,17 +6419,18 @@ void __stdcall glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GL index, x, y, z, w); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } GLuint vals[4] = { x, y, z, w }; @@ -6186,17 +6443,18 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } context->getState().setVertexAttribi(index, v); @@ -6208,17 +6466,18 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } context->getState().setVertexAttribu(index, v); @@ -6231,36 +6490,19 @@ void __stdcall glGetUniformuiv(GLuint program, GLint location, GLuint* params) program, location, params); gl::Context *context = gl::getNonLostContext(); - if (context) { - if (context->getClientVersion() < 3) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (program == 0) + if (!ValidateGetUniformuiv(context, program, location, params)) { - return gl::error(GL_INVALID_VALUE); + return; } gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } - + ASSERT(programObject); gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + ASSERT(programBinary); - if (!programBinary->getUniformuiv(location, NULL, params)) - { - return gl::error(GL_INVALID_OPERATION); - } + programBinary->getUniformuiv(location, params); } } @@ -6270,30 +6512,33 @@ GLint __stdcall glGetFragDataLocation(GLuint program, const GLchar *name) program, name); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION, -1); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return -1; } if (program == 0) { - return gl::error(GL_INVALID_VALUE, -1); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return -1; } gl::Program *programObject = context->getProgram(program); if (!programObject || !programObject->isLinked()) { - return gl::error(GL_INVALID_OPERATION, -1); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return -1; } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programBinary) { - return gl::error(GL_INVALID_OPERATION, -1); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return -1; } return programBinary->getFragDataLocation(name); @@ -6331,7 +6576,6 @@ void __stdcall glUniform1uiv(GLint location, GLsizei count, const GLuint* value) location, count, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count)) @@ -6350,7 +6594,6 @@ void __stdcall glUniform2uiv(GLint location, GLsizei count, const GLuint* value) location, count, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count)) @@ -6369,7 +6612,6 @@ void __stdcall glUniform3uiv(GLint location, GLsizei count, const GLuint* value) location, count, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count)) @@ -6388,7 +6630,6 @@ void __stdcall glUniform4uiv(GLint location, GLsizei count, const GLuint* value) location, count, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count)) @@ -6407,7 +6648,6 @@ void __stdcall glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* val buffer, drawbuffer, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateClearBuffer(context)) @@ -6420,20 +6660,30 @@ void __stdcall glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* val case GL_COLOR: if (drawbuffer < 0 || static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } break; + case GL_STENCIL: if (drawbuffer != 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - context->clearBufferiv(buffer, drawbuffer, value); + gl::Error error = context->clearBufferiv(buffer, drawbuffer, value); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -6443,7 +6693,6 @@ void __stdcall glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* v buffer, drawbuffer, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateClearBuffer(context)) @@ -6456,14 +6705,22 @@ void __stdcall glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* v case GL_COLOR: if (drawbuffer < 0 || static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - context->clearBufferuiv(buffer, drawbuffer, value); + gl::Error error = context->clearBufferuiv(buffer, drawbuffer, value); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -6473,7 +6730,6 @@ void __stdcall glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* v buffer, drawbuffer, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateClearBuffer(context)) @@ -6486,20 +6742,30 @@ void __stdcall glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* v case GL_COLOR: if (drawbuffer < 0 || static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } break; + case GL_DEPTH: if (drawbuffer != 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - context->clearBufferfv(buffer, drawbuffer, value); + gl::Error error = context->clearBufferfv(buffer, drawbuffer, value); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -6509,7 +6775,6 @@ void __stdcall glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, G buffer, drawbuffer, depth, stencil); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateClearBuffer(context)) @@ -6522,14 +6787,22 @@ void __stdcall glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, G case GL_DEPTH_STENCIL: if (drawbuffer != 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } - context->clearBufferfi(buffer, drawbuffer, depth, stencil); + gl::Error error = context->clearBufferfi(buffer, drawbuffer, depth, stencil); + if (error.isError()) + { + context->recordError(error); + return; + } } } @@ -6538,22 +6811,24 @@ const GLubyte* __stdcall 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) { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return NULL; } if (name != GL_EXTENSIONS) { - return gl::error(GL_INVALID_ENUM, reinterpret_cast(NULL)); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return NULL; } if (index >= context->getExtensionStringCount()) { - return gl::error(GL_INVALID_VALUE, reinterpret_cast(NULL)); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return NULL; } return reinterpret_cast(context->getExtensionString(index).c_str()); @@ -6568,17 +6843,18 @@ void __stdcall glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintp readTarget, writeTarget, readOffset, writeOffset, size); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (!gl::ValidBufferTarget(context, readTarget) || !gl::ValidBufferTarget(context, readTarget)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } gl::Buffer *readBuffer = context->getState().getTargetBuffer(readTarget); @@ -6586,32 +6862,40 @@ void __stdcall glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintp if (!readBuffer || !writeBuffer) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } + // Verify that readBuffer and writeBuffer are not currently mapped if (readBuffer->isMapped() || writeBuffer->isMapped()) { - return gl::error(GL_INVALID_OPERATION); + 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()) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } if (readBuffer == writeBuffer && abs(readOffset - writeOffset) < size) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } - // TODO: Verify that readBuffer and writeBuffer are not currently mapped (GL_INVALID_OPERATION) - // if size is zero, the copy is a successful no-op if (size > 0) { - writeBuffer->copyBufferSubData(readBuffer, readOffset, writeOffset, size); + gl::Error error = writeBuffer->copyBufferSubData(readBuffer, readOffset, writeOffset, size); + if (error.isError()) + { + context->recordError(error); + return; + } } } } @@ -6622,17 +6906,18 @@ void __stdcall glGetUniformIndices(GLuint program, GLsizei uniformCount, const G program, uniformCount, uniformNames, uniformIndices); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (uniformCount < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } gl::Program *programObject = context->getProgram(program); @@ -6641,11 +6926,13 @@ void __stdcall glGetUniformIndices(GLuint program, GLsizei uniformCount, const G { if (context->getShader(program)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } @@ -6673,17 +6960,18 @@ void __stdcall glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const program, uniformCount, uniformIndices, pname, params); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (uniformCount < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } gl::Program *programObject = context->getProgram(program); @@ -6692,11 +6980,13 @@ void __stdcall glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const { if (context->getShader(program)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } @@ -6711,15 +7001,18 @@ void __stdcall glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const case GL_UNIFORM_MATRIX_STRIDE: case GL_UNIFORM_IS_ROW_MAJOR: break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programBinary && uniformCount > 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } for (int uniformId = 0; uniformId < uniformCount; uniformId++) @@ -6728,7 +7021,8 @@ void __stdcall glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const if (index >= (GLuint)programBinary->getActiveUniformCount()) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } @@ -6745,12 +7039,12 @@ GLuint __stdcall glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlo EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION, GL_INVALID_INDEX); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_INVALID_INDEX; } gl::Program *programObject = context->getProgram(program); @@ -6759,11 +7053,13 @@ GLuint __stdcall glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlo { if (context->getShader(program)) { - return gl::error(GL_INVALID_OPERATION, GL_INVALID_INDEX); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_INVALID_INDEX; } else { - return gl::error(GL_INVALID_VALUE, GL_INVALID_INDEX); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return GL_INVALID_INDEX; } } @@ -6785,12 +7081,12 @@ void __stdcall glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockInde program, uniformBlockIndex, pname, params); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } gl::Program *programObject = context->getProgram(program); @@ -6798,11 +7094,13 @@ void __stdcall glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockInde { if (context->getShader(program)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } @@ -6810,7 +7108,8 @@ void __stdcall glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockInde if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } switch (pname) @@ -6829,7 +7128,8 @@ void __stdcall glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockInde break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -6840,12 +7140,12 @@ void __stdcall glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIn program, uniformBlockIndex, bufSize, length, uniformBlockName); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } gl::Program *programObject = context->getProgram(program); @@ -6854,11 +7154,13 @@ void __stdcall glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIn { if (context->getShader(program)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } @@ -6866,7 +7168,8 @@ void __stdcall glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIn if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } programBinary->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName); @@ -6879,17 +7182,18 @@ void __stdcall glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, G program, uniformBlockIndex, uniformBlockBinding); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - if (uniformBlockBinding >= context->getMaximumCombinedUniformBufferBindings()) + if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } gl::Program *programObject = context->getProgram(program); @@ -6898,11 +7202,13 @@ void __stdcall glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, G { if (context->getShader(program)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } else { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } } @@ -6911,7 +7217,8 @@ void __stdcall glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, G // if never linked, there won't be any uniform blocks if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding); @@ -6924,12 +7231,12 @@ void __stdcall glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GL mode, first, count, instanceCount); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } // glDrawArraysInstanced @@ -6943,12 +7250,12 @@ void __stdcall glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, mode, count, type, indices, instanceCount); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } // glDrawElementsInstanced @@ -6961,22 +7268,24 @@ GLsync __stdcall 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) { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(0)); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return 0; } if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) { - return gl::error(GL_INVALID_ENUM, reinterpret_cast(0)); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return 0; } if (flags != 0) { - return gl::error(GL_INVALID_VALUE, reinterpret_cast(0)); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return 0; } return context->createFenceSync(condition); @@ -6990,12 +7299,12 @@ GLboolean __stdcall glIsSync(GLsync sync) EVENT("(GLsync sync = 0x%0.8p)", sync); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION, GL_FALSE); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_FALSE; } return (context->getFenceSync(sync) != NULL); @@ -7009,17 +7318,18 @@ void __stdcall glDeleteSync(GLsync sync) EVENT("(GLsync sync = 0x%0.8p)", sync); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (sync != static_cast(0) && !context->getFenceSync(sync)) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } context->deleteFenceSync(sync); @@ -7032,24 +7342,26 @@ GLenum __stdcall glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeou sync, flags, timeout); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION, GL_WAIT_FAILED); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_WAIT_FAILED; } if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0) { - return gl::error(GL_INVALID_VALUE, GL_WAIT_FAILED); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return GL_WAIT_FAILED; } gl::FenceSync *fenceSync = context->getFenceSync(sync); if (!fenceSync) { - return gl::error(GL_INVALID_VALUE, GL_WAIT_FAILED); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return GL_WAIT_FAILED; } return fenceSync->clientWait(flags, timeout); @@ -7064,29 +7376,32 @@ void __stdcall glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) sync, flags, timeout); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (flags != 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } if (timeout != GL_TIMEOUT_IGNORED) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } gl::FenceSync *fenceSync = context->getFenceSync(sync); if (!fenceSync) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } fenceSync->serverWait(); @@ -7099,12 +7414,12 @@ void __stdcall glGetInteger64v(GLenum pname, GLint64* params) pname, params); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } GLenum nativeType; @@ -7131,24 +7446,26 @@ void __stdcall glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* sync, pname, bufSize, length, values); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (bufSize < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } gl::FenceSync *fenceSync = context->getFenceSync(sync); if (!fenceSync) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } switch (pname) @@ -7159,7 +7476,8 @@ void __stdcall glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* case GL_SYNC_FLAGS: values[0] = 0; break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -7170,30 +7488,40 @@ void __stdcall glGetInteger64i_v(GLenum target, GLuint index, GLint64* data) target, index, data); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + 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 >= context->getMaxTransformFeedbackBufferBindings()) - return gl::error(GL_INVALID_VALUE); + 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 >= context->getMaximumCombinedUniformBufferBindings()) - return gl::error(GL_INVALID_VALUE); + if (index >= caps.maxUniformBufferBindings) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; + } break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } if (!(context->getIndexedInteger64v(target, index, data))) @@ -7201,7 +7529,10 @@ void __stdcall glGetInteger64i_v(GLenum target, GLuint index, GLint64* data) GLenum nativeType; unsigned int numParams = 0; if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) - return gl::error(GL_INVALID_ENUM); + { + 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 @@ -7233,22 +7564,24 @@ void __stdcall glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* pa target, pname, params); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (!gl::ValidBufferTarget(context, target)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } if (!gl::ValidBufferParameter(context, pname)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } gl::Buffer *buffer = context->getState().getTargetBuffer(target); @@ -7256,7 +7589,8 @@ void __stdcall glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* pa if (!buffer) { // A null buffer means that "0" is bound to the requested buffer target - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } switch (pname) @@ -7289,17 +7623,18 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (count < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } for (int i = 0; i < count; i++) @@ -7314,17 +7649,18 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (count < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } for (int i = 0; i < count; i++) @@ -7339,12 +7675,12 @@ GLboolean __stdcall glIsSampler(GLuint sampler) EVENT("(GLuint sampler = %u)", sampler); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION, GL_FALSE); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_FALSE; } return context->isSampler(sampler); @@ -7358,22 +7694,24 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (sampler != 0 && !context->isSampler(sampler)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - if (unit >= context->getMaximumCombinedTextureImageUnits()) + if (unit >= context->getCaps().maxCombinedTextureImageUnits) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } context->bindSampler(unit, sampler); @@ -7385,15 +7723,15 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - if (!gl::ValidateSamplerObjectParameter(pname)) + if (!gl::ValidateSamplerObjectParameter(context, pname)) { return; } @@ -7405,7 +7743,8 @@ void __stdcall glSamplerParameteri(GLuint sampler, GLenum pname, GLint param) if (!context->isSampler(sampler)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } context->samplerParameteri(sampler, pname, param); @@ -7422,15 +7761,15 @@ void __stdcall 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - if (!gl::ValidateSamplerObjectParameter(pname)) + if (!gl::ValidateSamplerObjectParameter(context, pname)) { return; } @@ -7442,7 +7781,8 @@ void __stdcall glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) if (!context->isSampler(sampler)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } context->samplerParameterf(sampler, pname, param); @@ -7459,22 +7799,23 @@ void __stdcall glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* para EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname, params); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - if (!gl::ValidateSamplerObjectParameter(pname)) + if (!gl::ValidateSamplerObjectParameter(context, pname)) { return; } if (!context->isSampler(sampler)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } *params = context->getSamplerParameteri(sampler, pname); @@ -7486,22 +7827,23 @@ void __stdcall glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* pa EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - if (!gl::ValidateSamplerObjectParameter(pname)) + if (!gl::ValidateSamplerObjectParameter(context, pname)) { return; } if (!context->isSampler(sampler)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } *params = context->getSamplerParameterf(sampler, pname); @@ -7512,18 +7854,19 @@ void __stdcall glVertexAttribDivisor(GLuint index, GLuint divisor) { EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor); - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; + } + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } context->setVertexAttribDivisor(index, divisor); @@ -7535,12 +7878,12 @@ void __stdcall glBindTransformFeedback(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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } switch (target) @@ -7551,13 +7894,15 @@ void __stdcall glBindTransformFeedback(GLenum target, GLuint id) gl::TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback(); if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) { - return gl::error(GL_INVALID_OPERATION); + 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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } context->bindTransformFeedback(id); @@ -7565,7 +7910,8 @@ void __stdcall glBindTransformFeedback(GLenum target, GLuint id) break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -7575,12 +7921,12 @@ void __stdcall glDeleteTransformFeedbacks(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 (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } for (int i = 0; i < n; i++) @@ -7595,12 +7941,12 @@ void __stdcall glGenTransformFeedbacks(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) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } for (int i = 0; i < n; i++) @@ -7615,12 +7961,12 @@ GLboolean __stdcall glIsTransformFeedback(GLuint id) EVENT("(GLuint id = %u)", id); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION, GL_FALSE); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_FALSE; } return ((context->getTransformFeedback(id) != NULL) ? GL_TRUE : GL_FALSE); @@ -7634,12 +7980,12 @@ void __stdcall glPauseTransformFeedback(void) EVENT("(void)"); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); @@ -7648,7 +7994,8 @@ void __stdcall glPauseTransformFeedback(void) // Current transform feedback must be started and not paused in order to pause (3.0.2 pg 86) if (!transformFeedback->isStarted() || transformFeedback->isPaused()) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } transformFeedback->pause(); @@ -7660,12 +8007,12 @@ void __stdcall glResumeTransformFeedback(void) EVENT("(void)"); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); @@ -7674,7 +8021,8 @@ void __stdcall glResumeTransformFeedback(void) // Current transform feedback must be started and paused in order to resume (3.0.2 pg 86) if (!transformFeedback->isStarted() || !transformFeedback->isPaused()) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } transformFeedback->resume(); @@ -7687,12 +8035,12 @@ void __stdcall glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* leng program, bufSize, length, binaryFormat, binary); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } // glGetProgramBinary @@ -7706,12 +8054,12 @@ void __stdcall glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid program, binaryFormat, binary, length); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } // glProgramBinary @@ -7725,12 +8073,12 @@ void __stdcall glProgramParameteri(GLuint program, GLenum pname, GLint value) program, pname, value); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } // glProgramParameteri @@ -7744,12 +8092,12 @@ void __stdcall glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, co target, numAttachments, attachments); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) @@ -7757,8 +8105,11 @@ void __stdcall glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, co return; } - GLuint maxDimension = context->getCaps().maxRenderbufferSize; - context->invalidateFrameBuffer(target, numAttachments, attachments, 0, 0, maxDimension, maxDimension); + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + if (framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) + { + framebuffer->invalidate(context->getCaps(), numAttachments, attachments); + } } } @@ -7769,12 +8120,12 @@ void __stdcall glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, target, numAttachments, attachments, x, y, width, height); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) @@ -7782,7 +8133,11 @@ void __stdcall glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, return; } - context->invalidateFrameBuffer(target, numAttachments, attachments, x, y, width, height); + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + if (framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) + { + framebuffer->invalidateSub(context->getCaps(), numAttachments, attachments, x, y, width, height); + } } } @@ -7792,12 +8147,12 @@ void __stdcall glTexStorage2D(GLenum target, GLsizei levels, GLenum internalform target, levels, internalformat, width, height); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) @@ -7822,7 +8177,8 @@ void __stdcall glTexStorage2D(GLenum target, GLsizei levels, GLenum internalform break; default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -7834,12 +8190,12 @@ void __stdcall glTexStorage3D(GLenum target, GLsizei levels, GLenum internalform target, levels, internalformat, width, height, depth); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, depth)) @@ -7876,41 +8232,49 @@ void __stdcall glGetInternalformativ(GLenum target, GLenum internalformat, GLenu target, internalformat, pname, bufSize, params); gl::Context *context = gl::getNonLostContext(); - if (context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); if (!formatCaps.renderable) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } if (target != GL_RENDERBUFFER) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } if (bufSize < 0) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } switch (pname) { case GL_NUM_SAMPLE_COUNTS: if (bufSize != 0) - *params = context->getNumSampleCounts(internalformat); + { + *params = formatCaps.sampleCounts.size(); + } break; + case GL_SAMPLES: - context->getSampleCounts(internalformat, bufSize, params); + std::copy_n(formatCaps.sampleCounts.rbegin(), std::min(bufSize, formatCaps.sampleCounts.size()), params); break; + default: - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } } } @@ -7926,7 +8290,6 @@ void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLi srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, @@ -7959,29 +8322,29 @@ void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *l program, bufSize, length, binaryFormat, binary); gl::Context *context = gl::getNonLostContext(); - if (context) { gl::Program *programObject = context->getProgram(program); if (!programObject || !programObject->isLinked()) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } gl::ProgramBinary *programBinary = programObject->getProgramBinary(); if (!programBinary) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - if (!programBinary->save(binary, bufSize, length)) + if (!programBinary->save(binaryFormat, binary, bufSize, length)) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - - *binaryFormat = GL_PROGRAM_BINARY_ANGLE; } } @@ -7992,22 +8355,23 @@ void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat, program, binaryFormat, binary, length); gl::Context *context = gl::getNonLostContext(); - if (context) { - if (binaryFormat != GL_PROGRAM_BINARY_ANGLE) + const std::vector &programBinaryFormats = context->getCaps().programBinaryFormats; + if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) == programBinaryFormats.end()) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } gl::Program *programObject = context->getProgram(program); - if (!programObject) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } - context->setProgramBinary(program, binary, length); + context->setProgramBinary(program, binaryFormat, binary, length); } } @@ -8016,24 +8380,26 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs) 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) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } if (context->getState().getDrawFramebuffer()->id() == 0) { if (n != 1) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (bufs[0] != GL_NONE && bufs[0] != GL_BACK) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } } else @@ -8043,7 +8409,8 @@ void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs) const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment; if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } } } @@ -8067,17 +8434,18 @@ void __stdcall 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)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } if (pname != GL_BUFFER_MAP_POINTER) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } gl::Buffer *buffer = context->getState().getTargetBuffer(target); @@ -8098,32 +8466,42 @@ void * __stdcall 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)) { - return gl::error(GL_INVALID_ENUM, reinterpret_cast(NULL)); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return NULL; } gl::Buffer *buffer = context->getState().getTargetBuffer(target); if (buffer == NULL) { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return NULL; } if (access != GL_WRITE_ONLY_OES) { - return gl::error(GL_INVALID_ENUM, reinterpret_cast(NULL)); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return NULL; } if (buffer->isMapped()) { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return NULL; } - return buffer->mapRange(0, buffer->getSize(), GL_MAP_WRITE_BIT); + 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; @@ -8134,24 +8512,30 @@ GLboolean __stdcall glUnmapBufferOES(GLenum target) EVENT("(GLenum target = 0x%X)", target); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!gl::ValidBufferTarget(context, target)) { - return gl::error(GL_INVALID_ENUM, GL_FALSE); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return GL_FALSE; } gl::Buffer *buffer = context->getState().getTargetBuffer(target); if (buffer == NULL || !buffer->isMapped()) { - return gl::error(GL_INVALID_OPERATION, GL_FALSE); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return GL_FALSE; } // TODO: detect if we had corruption. if so, throw an error and return false. - buffer->unmap(); + gl::Error error = buffer->unmap(); + if (error.isError()) + { + context->recordError(error); + return GL_FALSE; + } return GL_TRUE; } @@ -8165,24 +8549,26 @@ void* __stdcall glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr target, offset, length, access); gl::Context *context = gl::getNonLostContext(); - if (context) { if (!gl::ValidBufferTarget(context, target)) { - return gl::error(GL_INVALID_ENUM, reinterpret_cast(NULL)); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return NULL; } if (offset < 0 || length < 0) { - return gl::error(GL_INVALID_VALUE, reinterpret_cast(NULL)); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return NULL; } gl::Buffer *buffer = context->getState().getTargetBuffer(target); if (buffer == NULL) { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return NULL; } // Check for buffer overflow @@ -8192,7 +8578,8 @@ void* __stdcall glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || offsetSize + lengthSize > static_cast(buffer->getSize())) { - return gl::error(GL_INVALID_VALUE, reinterpret_cast(NULL)); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return NULL; } // Check for invalid bits in the mask @@ -8205,18 +8592,21 @@ void* __stdcall glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr if (access & ~(allAccessBits)) { - return gl::error(GL_INVALID_VALUE, reinterpret_cast(NULL)); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return NULL; } if (length == 0 || buffer->isMapped()) { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); + 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) { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return NULL; } GLbitfield writeOnlyBits = GL_MAP_INVALIDATE_RANGE_BIT | @@ -8225,15 +8615,24 @@ void* __stdcall glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0) { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return NULL; } if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0) { - return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); + 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->mapRange(offset, length, access); + return buffer->getMapPointer(); } return NULL; @@ -8244,29 +8643,32 @@ void __stdcall glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsi 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) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } if (!gl::ValidBufferTarget(context, target)) { - return gl::error(GL_INVALID_ENUM); + context->recordError(gl::Error(GL_INVALID_ENUM)); + return; } gl::Buffer *buffer = context->getState().getTargetBuffer(target); if (buffer == NULL) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) { - return gl::error(GL_INVALID_OPERATION); + context->recordError(gl::Error(GL_INVALID_OPERATION)); + return; } // Check for buffer overflow @@ -8276,7 +8678,8 @@ void __stdcall glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsi if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || offsetSize + lengthSize > static_cast(buffer->getMapLength())) { - return gl::error(GL_INVALID_VALUE); + context->recordError(gl::Error(GL_INVALID_VALUE)); + return; } // We do not currently support a non-trivial implementation of FlushMappedBufferRange @@ -8347,7 +8750,6 @@ bool __stdcall glBindTexImage(egl::Surface *surface) surface); gl::Context *context = gl::getNonLostContext(); - if (context) { gl::Texture2D *textureObject = context->getTexture2D(); diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def index 88dceb3556..33557eb1c9 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/libGLESv2_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def index d6272c4df9..18ffcf6a0d 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def @@ -294,6 +294,3 @@ EXPORTS 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 d301aa0905..120371e013 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.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/libGLESv2d_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def index a82d629ae4..8c1306a703 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def @@ -294,6 +294,3 @@ EXPORTS 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 index 8820700c76..51447e273a 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.cpp +++ b/src/3rdparty/angle/src/libGLESv2/main.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -175,33 +174,26 @@ egl::Display *getDisplay() void error(GLenum errorCode) { gl::Context *context = glGetCurrentContext(); + context->recordError(Error(errorCode)); - if (context) + switch (errorCode) { - switch (errorCode) - { - case GL_INVALID_ENUM: - context->recordInvalidEnum(); - TRACE("\t! Error generated: invalid enum\n"); - break; - case GL_INVALID_VALUE: - context->recordInvalidValue(); - TRACE("\t! Error generated: invalid value\n"); - break; - case GL_INVALID_OPERATION: - context->recordInvalidOperation(); - TRACE("\t! Error generated: invalid operation\n"); - break; - case GL_OUT_OF_MEMORY: - context->recordOutOfMemory(); - TRACE("\t! Error generated: out of memory\n"); - break; - case GL_INVALID_FRAMEBUFFER_OPERATION: - context->recordInvalidFramebufferOperation(); - TRACE("\t! Error generated: invalid framebuffer operation\n"); - break; - default: UNREACHABLE(); - } + case GL_INVALID_ENUM: + TRACE("\t! Error generated: invalid enum\n"); + break; + case GL_INVALID_VALUE: + TRACE("\t! Error generated: invalid value\n"); + break; + case GL_INVALID_OPERATION: + TRACE("\t! Error generated: invalid operation\n"); + break; + case GL_OUT_OF_MEMORY: + TRACE("\t! Error generated: out of memory\n"); + break; + case GL_INVALID_FRAMEBUFFER_OPERATION: + TRACE("\t! Error generated: invalid framebuffer operation\n"); + break; + default: UNREACHABLE(); } } diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h index df28ea400d..c30ad3375c 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.h +++ b/src/3rdparty/angle/src/libGLESv2/main.h @@ -10,8 +10,8 @@ #define LIBGLESV2_MAIN_H_ #include "common/debug.h" -#undef EGLAPI -#define EGLAPI + +#include #include #ifndef Sleep diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.cpp b/src/3rdparty/angle/src/libGLESv2/precompiled.cpp deleted file mode 100644 index 2621cd6ce3..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/precompiled.cpp +++ /dev/null @@ -1,9 +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. -// - -// precompiled.cpp: Precompiled header source file for libGLESv2. - -#include "precompiled.h" diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.h b/src/3rdparty/angle/src/libGLESv2/precompiled.h deleted file mode 100644 index 0404eabf8a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/precompiled.h +++ /dev/null @@ -1,32 +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. -// - -// precompiled.h: Precompiled header file for libGLESv2. - -#include "angle_gl.h" -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include // for std::min and std::max -#include -#include -#include -#include -#include -#include -#include -#include diff --git a/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp b/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp index 67578efe3a..7245902c51 100644 --- a/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp +++ b/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp @@ -1,4 +1,3 @@ -#include "precompiled.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 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h index bea689b956..f0b5f02227 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h @@ -20,12 +20,12 @@ class BufferImpl public: virtual ~BufferImpl() { } - virtual void setData(const void* data, size_t size, GLenum usage) = 0; + virtual gl::Error setData(const void* data, size_t size, GLenum usage) = 0; virtual void *getData() = 0; - virtual void setSubData(const void* data, size_t size, size_t offset) = 0; - virtual void copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) = 0; - virtual GLvoid* map(size_t offset, size_t length, GLbitfield access) = 0; - virtual void unmap() = 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; }; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp index 5963534e03..370b086233 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h b/src/3rdparty/angle/src/libGLESv2/renderer/Image.h index 8fcffa4309..3bfc663762 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image.h @@ -13,6 +13,8 @@ #include "common/debug.h" +#include + namespace gl { class Framebuffer; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp index e957d96270..f68ac383de 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -10,16 +9,49 @@ #include "libGLESv2/renderer/IndexRangeCache.h" #include "libGLESv2/formatutils.h" + #include "common/debug.h" + #include namespace rx { -void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, unsigned int minIdx, unsigned int maxIdx, +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(minIdx, maxIdx, streamOffset); + mIndexRangeCache[IndexRange(type, offset, count)] = IndexBounds(range, streamOffset); } void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size) @@ -31,7 +63,7 @@ void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size) while (i != mIndexRangeCache.end()) { unsigned int rangeStart = i->second.streamOffset; - unsigned int rangeEnd = i->second.streamOffset + (gl::GetTypeBytes(i->first.type) * i->first.count); + unsigned int rangeEnd = i->second.streamOffset + (gl::GetTypeInfo(i->first.type).bytes * i->first.count); if (invalidateEnd < rangeStart || invalidateStart > rangeEnd) { @@ -44,21 +76,19 @@ void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size) } } -bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count, unsigned int *outMinIndex, - unsigned int *outMaxIndex, unsigned int *outStreamOffset) const +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 (outMinIndex) *outMinIndex = i->second.minIndex; - if (outMaxIndex) *outMaxIndex = i->second.maxIndex; + if (outRange) *outRange = i->second.range; if (outStreamOffset) *outStreamOffset = i->second.streamOffset; return true; } else { - if (outMinIndex) *outMinIndex = 0; - if (outMaxIndex) *outMaxIndex = 0; + if (outRange) *outRange = RangeUI(0, 0); if (outStreamOffset) *outStreamOffset = 0; return false; } @@ -89,12 +119,13 @@ bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const } IndexRangeCache::IndexBounds::IndexBounds() - : minIndex(0), maxIndex(0), streamOffset(0) + : range(0, 0), + streamOffset(0) { } -IndexRangeCache::IndexBounds::IndexBounds(unsigned int minIdx, unsigned int maxIdx, unsigned int offset) - : minIndex(minIdx), maxIndex(maxIdx), streamOffset(offset) +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 index 837a44acd3..a7d91e035b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h @@ -11,6 +11,10 @@ #define LIBGLESV2_RENDERER_INDEXRANGECACHE_H_ #include "common/angleutils.h" +#include "common/mathutil.h" + +#include "angle_gl.h" + #include namespace rx @@ -19,14 +23,16 @@ namespace rx class IndexRangeCache { public: - void addRange(GLenum type, unsigned int offset, GLsizei count, unsigned int minIdx, unsigned int maxIdx, + void addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range, unsigned int streamOffset); - bool findRange(GLenum type, unsigned int offset, GLsizei count, unsigned int *outMinIndex, - unsigned int *outMaxIndex, unsigned int *outStreamOffset) const; + 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 { @@ -42,12 +48,11 @@ class IndexRangeCache struct IndexBounds { - unsigned int minIndex; - unsigned int maxIndex; + RangeUI range; unsigned int streamOffset; IndexBounds(); - IndexBounds(unsigned int minIdx, unsigned int maxIdx, unsigned int offset); + IndexBounds(const RangeUI &range, unsigned int offset); }; typedef std::map IndexRangeMap; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h new file mode 100644 index 0000000000..ba0955fdf8 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h @@ -0,0 +1,58 @@ +// +// 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" + +namespace rx +{ + +class DynamicHLSL; +class Renderer; + +class ProgramImpl +{ +public: + virtual ~ProgramImpl() { } + + // TODO: Temporary interfaces to ease migration. Remove soon! + virtual Renderer *getRenderer() = 0; + virtual DynamicHLSL *getDynamicHLSL() = 0; + virtual const std::vector &getPixelShaderKey() = 0; + + virtual GLenum getBinaryFormat() = 0; + virtual bool load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0; + virtual bool save(gl::BinaryOutputStream *stream) = 0; + + virtual rx::ShaderExecutable *getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector &outputSignature, + const std::vector &transformFeedbackLinkedVaryings, + bool separatedOutputBuffers) = 0; + virtual rx::ShaderExecutable *getVertexExecutableForInputLayout(gl::InfoLog &infoLog, + const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], + const sh::Attribute shaderAttributes[], + const std::vector &transformFeedbackLinkedVaryings, + bool separatedOutputBuffers) = 0; + + virtual bool link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, + const std::vector &transformFeedbackVaryings, int *registers, + std::vector *linkedVaryings, std::map *outputVariables) = 0; + + virtual void initializeUniformStorage(const std::vector &uniforms) = 0; + + virtual void reset() = 0; +}; + +} + +#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 index a6750a204b..6b45810a3b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h @@ -9,28 +9,27 @@ #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), mStatus(GL_FALSE), mResult(0) { } + explicit QueryImpl(GLenum type) { mType = type; } virtual ~QueryImpl() { } - virtual void begin() = 0; - virtual void end() = 0; - virtual GLuint getResult() = 0; - virtual GLboolean isResultAvailable() = 0; - virtual bool isStarted() const = 0; - - GLenum getType() const { return mType; } + virtual gl::Error begin() = 0; + virtual gl::Error end() = 0; + virtual gl::Error getResult(GLuint *params) = 0; + virtual gl::Error isResultAvailable(GLuint *available) = 0; - protected: - GLuint mResult; - GLboolean mStatus; + GLenum getType() const { return mType; } private: DISALLOW_COPY_AND_ASSIGN(QueryImpl); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp index 590004ac9b..910d0285f1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -7,12 +6,10 @@ // Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances. -#include #include "libGLESv2/main.h" #include "libGLESv2/Program.h" #include "libGLESv2/renderer/Renderer.h" #include "common/utilities.h" -#include "third_party/trace_event/trace_event.h" #include "libGLESv2/Shader.h" #if defined (ANGLE_ENABLE_D3D9) @@ -23,11 +20,17 @@ #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 +#include + namespace rx { @@ -40,7 +43,6 @@ Renderer::Renderer(egl::Display *display) Renderer::~Renderer() { - gl::Shader::releaseCompiler(); } const gl::Caps &Renderer::getRendererCaps() const diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h index f1e0fd2d99..b2249741ab 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h @@ -13,9 +13,13 @@ #include "libGLESv2/Uniform.h" #include "libGLESv2/angletypes.h" #include "libGLESv2/Caps.h" +#include "libGLESv2/Error.h" + +#include + +#include #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) -#include // 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 @@ -40,10 +44,7 @@ struct VertexAttribCurrentValueData; namespace rx { -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; -class TextureStorageInterface3D; -class TextureStorageInterface2DArray; +class TextureStorage; class VertexBuffer; class IndexBuffer; class QueryImpl; @@ -52,16 +53,16 @@ class BufferImpl; class VertexArrayImpl; class BufferStorage; struct TranslatedIndexData; +class ShaderImpl; +class ProgramImpl; class ShaderExecutable; class SwapChain; class RenderTarget; class Image; class TextureStorage; class UniformStorage; -class Texture2DImpl; -class TextureCubeImpl; -class Texture3DImpl; -class Texture2DArrayImpl; +class TextureImpl; +class TransformFeedbackImpl; struct ConfigDesc { @@ -108,37 +109,37 @@ class Renderer virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0; - virtual void generateSwizzle(gl::Texture *texture) = 0; - virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler) = 0; - virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0; + virtual gl::Error generateSwizzle(gl::Texture *texture) = 0; + virtual gl::Error setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler) = 0; + virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0; - virtual bool setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) = 0; + virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) = 0; - virtual void setRasterizerState(const gl::RasterizerState &rasterState) = 0; - virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) = 0; - virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW) = 0; + virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState) = 0; + virtual gl::Error setBlendState(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 bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, bool ignoreViewport) = 0; - virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer) = 0; - virtual void applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, bool transformFeedbackActive) = 0; - virtual void applyUniforms(const gl::ProgramBinary &programBinary) = 0; + virtual gl::Error applyRenderTarget(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 gl::ProgramBinary &programBinary) = 0; virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0; - virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], - GLint first, GLsizei count, GLsizei instances) = 0; - virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0; + virtual gl::Error applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], + 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(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) = 0; - virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) = 0; - virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0; + 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 void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) = 0; + virtual gl::Error clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) = 0; virtual void markAllStateDirty() = 0; @@ -157,62 +158,48 @@ class Renderer virtual std::string getRendererDescription() const = 0; virtual GUID getAdapterIdentifier() const = 0; - bool getVertexTextureSupport() const { return getMaxVertexTextureImageUnits() > 0; } - virtual unsigned int getMaxVertexTextureImageUnits() const = 0; - virtual unsigned int getMaxCombinedTextureImageUnits() const = 0; virtual unsigned int getReservedVertexUniformVectors() const = 0; virtual unsigned int getReservedFragmentUniformVectors() const = 0; - virtual unsigned int getMaxVertexUniformVectors() const = 0; - virtual unsigned int getMaxFragmentUniformVectors() const = 0; - virtual unsigned int getMaxVaryingVectors() const = 0; - virtual unsigned int getMaxVertexShaderUniformBuffers() const = 0; - virtual unsigned int getMaxFragmentShaderUniformBuffers() const = 0; virtual unsigned int getReservedVertexUniformBuffers() const = 0; virtual unsigned int getReservedFragmentUniformBuffers() const = 0; - virtual unsigned int getMaxTransformFeedbackBuffers() const = 0; - virtual unsigned int getMaxTransformFeedbackSeparateComponents() const = 0; - virtual unsigned int getMaxTransformFeedbackInterleavedComponents() const = 0; - virtual unsigned int getMaxUniformBufferSize() const = 0; virtual bool getShareHandleSupport() const = 0; virtual bool getPostSubBufferSupport() const = 0; - virtual int getMaxRecommendedElementsIndices() const = 0; - virtual int getMaxRecommendedElementsVertices() const = 0; - virtual bool getSRGBTextureSupport() const = 0; virtual int getMajorShaderModel() const = 0; virtual int getMinSwapInterval() const = 0; virtual int getMaxSwapInterval() const = 0; - virtual GLsizei getMaxSupportedSamples() const = 0; - virtual GLsizei getMaxSupportedFormatSamples(GLenum internalFormat) const = 0; - virtual GLsizei getNumSampleCounts(GLenum internalFormat) const = 0; - virtual void getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const = 0; - // Pixel operations - virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) = 0; - virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) = 0; - virtual bool copyToRenderTarget(TextureStorageInterface3D *dest, TextureStorageInterface3D *source) = 0; - virtual bool copyToRenderTarget(TextureStorageInterface2DArray *dest, TextureStorageInterface2DArray *source) = 0; - - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) = 0; - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) = 0; - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface3D *storage, GLint level) = 0; - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level) = 0; + virtual bool copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source) = 0; + virtual bool copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source) = 0; + virtual bool copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source) = 0; + virtual bool copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source) = 0; + + virtual bool copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) = 0; + virtual bool copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) = 0; + virtual bool copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0; + virtual bool copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0; virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) = 0; - virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels) = 0; + + virtual gl::Error readPixels(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 RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth) = 0; virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples) = 0; + // Shader creation + virtual ShaderImpl *createShader(GLenum type) = 0; + virtual ProgramImpl *createProgram() = 0; + // Shader operations + virtual void releaseShaderCompiler() = 0; virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, const std::vector &transformFeedbackVaryings, bool separatedOutputBuffers) = 0; @@ -231,10 +218,7 @@ class Renderer virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; // Texture creation - virtual Texture2DImpl *createTexture2D() = 0; - virtual TextureCubeImpl *createTextureCube() = 0; - virtual Texture3DImpl *createTexture3D() = 0; - virtual Texture2DArrayImpl *createTexture2DArray() = 0; + virtual TextureImpl *createTexture(GLenum target) = 0; // Buffer creation virtual BufferImpl *createBuffer() = 0; @@ -248,6 +232,9 @@ class Renderer virtual QueryImpl *createQuery(GLenum type) = 0; virtual FenceImpl *createFence() = 0; + // Transform Feedback creation + virtual TransformFeedbackImpl* createTransformFeedback() = 0; + // Current GLES client version void setCurrentClientVersion(int clientVersion) { mCurrentClientVersion = clientVersion; } int getCurrentClientVersion() const { return mCurrentClientVersion; } @@ -258,7 +245,6 @@ class Renderer GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0; virtual bool getLUID(LUID *adapterLuid) const = 0; - virtual GLenum getNativeTextureFormat(GLenum internalFormat) const = 0; virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const = 0; virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const = 0; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h index 054d00a712..f17195673d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h @@ -13,6 +13,9 @@ #include "common/angleutils.h" #include "common/debug.h" +#include +#include + namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h new file mode 100644 index 0000000000..de5d30e6fe --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h @@ -0,0 +1,54 @@ +// +// 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 std::string &source) = 0; + virtual const std::string &getInfoLog() const = 0; + virtual const std::string &getTranslatedSource() 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 index 77546f81e7..1ec702f299 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h @@ -10,12 +10,12 @@ #ifndef LIBGLESV2_RENDERER_SWAPCHAIN_H_ #define LIBGLESV2_RENDERER_SWAPCHAIN_H_ -#include #include "common/angleutils.h" +#include "common/platform.h" -#if !defined(ANGLE_FORCE_VSYNC_OFF) -#define ANGLE_FORCE_VSYNC_OFF 0 -#endif +#include +#include +#include namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h index 35c9166023..e3cc50d680 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h @@ -11,6 +11,10 @@ #include "common/angleutils.h" +#include "angle_gl.h" + +#include "libGLESv2/ImageIndex.h" + namespace egl { class Surface; @@ -27,138 +31,38 @@ namespace rx { class Image; -class RenderTarget; class Renderer; -class TextureStorageInterface; +class TextureStorage; -class Texture2DImpl +class TextureImpl { public: - virtual ~Texture2DImpl() {} + virtual ~TextureImpl() {}; // TODO: If this methods could go away that would be ideal; // TextureStorage should only be necessary for the D3D backend, and as such // higher level code should not rely on it. - virtual TextureStorageInterface *getNativeTexture() = 0; - - virtual Image *getImage(int level) const = 0; - - virtual void setUsage(GLenum usage) = 0; - virtual bool hasDirtyImages() const = 0; - virtual void resetDirty() = 0; - - virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const = 0; - virtual void bindTexImage(egl::Surface *surface) = 0; - virtual void releaseTexImage() = 0; - - virtual void setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; - virtual void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) = 0; - virtual void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; - virtual void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) = 0; - virtual void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; - virtual void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) = 0; - virtual void generateMipmaps() = 0; - - virtual unsigned int getRenderTargetSerial(GLint level) = 0; - - virtual RenderTarget *getRenderTarget(GLint level) = 0; - virtual RenderTarget *getDepthSencil(GLint level) = 0; - - virtual void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height) = 0; -}; - -class TextureCubeImpl -{ - public: - virtual ~TextureCubeImpl() {} - - virtual TextureStorageInterface *getNativeTexture() = 0; - - virtual Image *getImage(GLenum target, int level) const = 0; - - virtual void setUsage(GLenum usage) = 0; - virtual bool hasDirtyImages() const = 0; - virtual void resetDirty() = 0; - - virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const = 0; - virtual bool isCubeComplete() const = 0; - - virtual void setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; - virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) = 0; - virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; - virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) = 0; - virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; - virtual void storage(GLsizei levels, GLenum internalformat, GLsizei size) = 0; - virtual void generateMipmaps() = 0; - - virtual unsigned int getRenderTargetSerial(GLenum target, GLint level) = 0; - - virtual RenderTarget *getRenderTarget(GLenum target, GLint level) = 0; - virtual RenderTarget *getDepthStencil(GLenum target, GLint level) = 0; -}; - -class Texture3DImpl -{ - public: - virtual ~Texture3DImpl() {} - - virtual TextureStorageInterface *getNativeTexture() = 0; - - virtual Image *getImage(int level) const = 0; - - virtual void setUsage(GLenum usage) = 0; - virtual bool hasDirtyImages() const = 0; - virtual void resetDirty() = 0; - - virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const = 0; - virtual bool isMipmapComplete() const = 0; - - virtual void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; - virtual void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) = 0; - virtual void subImage(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 void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) = 0; - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; - virtual void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = 0; - virtual void generateMipmaps() = 0; - - virtual unsigned int getRenderTargetSerial(GLint level, GLint layer) = 0; - - virtual RenderTarget *getRenderTarget(GLint level) = 0; - virtual RenderTarget *getRenderTarget(GLint level, GLint layer) = 0; - virtual RenderTarget *getDepthStencil(GLint level, GLint layer) = 0; -}; - -class Texture2DArrayImpl -{ - public: - virtual ~Texture2DArrayImpl() {} - - virtual TextureStorageInterface *getNativeTexture() = 0; + virtual TextureStorage *getNativeTexture() = 0; + // 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 bool hasDirtyImages() const = 0; - virtual void resetDirty() = 0; - virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const = 0; - virtual bool isMipmapComplete() const = 0; - - virtual void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0; - virtual void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) = 0; - virtual void subImage(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 void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) = 0; + virtual void 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 void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) = 0; + virtual void 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 void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) = 0; + virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; - virtual void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = 0; - virtual void generateMipmaps() = 0; + virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = 0; - virtual unsigned int getRenderTargetSerial(GLint level, GLint layer) = 0; + virtual void generateMipmaps() = 0; - virtual RenderTarget *getRenderTarget(GLint level, GLint layer) = 0; - virtual RenderTarget *getDepthStencil(GLint level, GLint layer) = 0; + virtual void bindTexImage(egl::Surface *surface) = 0; + virtual void releaseTexImage() = 0; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h new file mode 100644 index 0000000000..8425604d87 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/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 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/copyimage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp index 765089cc96..004223d70f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -12,12 +11,12 @@ namespace rx { -void CopyBGRAUByteToRGBAUByte(const void *source, void *dest) +void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest) { - unsigned int argb = *(unsigned int*)source; - *(unsigned int*)dest = (argb & 0xFF00FF00) | // Keep alpha and green - (argb & 0x00FF0000) >> 16 | // Move red to blue - (argb & 0x000000FF) << 16; // Move blue to red + 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 index 9b94404ee3..513eb5cb3d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -12,31 +12,24 @@ #include "common/mathutil.h" #include "libGLESv2/angletypes.h" +#include + namespace rx { template -void ReadColor(const void *source, void *dest) -{ - sourceType::readColor(reinterpret_cast*>(dest), reinterpret_cast(source)); -} +void ReadColor(const uint8_t *source, uint8_t *dest); template -void WriteColor(const void *source, void *dest) -{ - destType::writeColor(reinterpret_cast(dest), reinterpret_cast*>(source)); -} +void WriteColor(const uint8_t *source, uint8_t *dest); template -void CopyPixel(const void *source, void *dest) -{ - colorDataType temp; - ReadColor(source, &temp); - WriteColor(&temp, dest); -} +void CopyPixel(const uint8_t *source, uint8_t *dest); -void CopyBGRAUByteToRGBAUByte(const void *source, void *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 new file mode 100644 index 0000000000..0498cf7750 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/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/libGLESv2/renderer/copyvertex.h b/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h index aca031701e..e0e8af166b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -11,299 +11,25 @@ #include "common/mathutil.h" -// '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 copyVertexData(const void *input, size_t stride, size_t count, void *output) -{ - const unsigned int 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 - { - unsigned int outputStride = widen ? 4 : componentCount; - - for (unsigned int i = 0; i < count; i++) - { - const T *offsetInput = reinterpret_cast(reinterpret_cast(input) + i * stride); - T *offsetOutput = reinterpret_cast(output) + i * outputStride; - - for (unsigned int j = 0; j < componentCount; j++) - { - offsetOutput[j] = offsetInput[j]; - } - - if (widen) - { - offsetOutput[3] = defaultValue; - } - } - } -} - -template -inline void copyFixedVertexData(const void* input, size_t stride, size_t count, void* output) +namespace rx { - static const float divisor = 1.0f / (1 << 16); - - for (unsigned int i = 0; i < count; i++) - { - const GLfixed* offsetInput = reinterpret_cast(reinterpret_cast(input) + stride * i); - float* offsetOutput = reinterpret_cast(output) + i * componentCount; - for (unsigned int j = 0; j < componentCount; j++) - { - offsetOutput[j] = static_cast(offsetInput[j]) * divisor; - } - } -} - -template -inline void copyToFloatVertexData(const void* input, size_t stride, size_t count, void* output) -{ - typedef std::numeric_limits NL; - - for (unsigned int i = 0; i < count; i++) - { - const T *offsetInput = reinterpret_cast(reinterpret_cast(input) + stride * i); - float *offsetOutput = reinterpret_cast(output) + i * componentCount; - - for (unsigned int j = 0; j < componentCount; j++) - { - if (normalized) - { - if (NL::is_signed) - { - const float divisor = 1.0f / (2 * static_cast(NL::max()) + 1); - offsetOutput[j] = (2 * static_cast(offsetInput[j]) + 1) * divisor; - } - else - { - offsetOutput[j] = static_cast(offsetInput[j]) / NL::max(); - } - } - else - { - offsetOutput[j] = static_cast(offsetInput[j]); - } - } - } -} - -inline void copyPackedUnsignedVertexData(const void* input, size_t stride, size_t count, void* output) -{ - const unsigned int attribSize = 4; +// '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); - if (attribSize == stride) - { - memcpy(output, input, count * attribSize); - } - else - { - for (unsigned int i = 0; i < count; i++) - { - const GLuint *offsetInput = reinterpret_cast(reinterpret_cast(input) + (i * stride)); - GLuint *offsetOutput = reinterpret_cast(output) + (i * attribSize); +template +inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); - offsetOutput[i] = offsetInput[i]; - } - } -} +template +inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); template -static inline void copyPackedRGB(unsigned int data, void *output) -{ - const unsigned int rgbSignMask = 0x200; // 1 set at the 9 bit - const unsigned int 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 int maxValue = 0x1FF; // 1 set in bits 0 through 8 - const int 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 int halfRange = (maxValue - minValue) >> 1; - *floatOutput = ((finalValue - minValue) / halfRange) - 1.0f; - } - else - { - *floatOutput = finalValue; - } - } - else - { - if (normalized) - { - const unsigned int 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; - } - } -} +inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output); -template -inline void copyPackedAlpha(unsigned int data, void *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 copyPackedVertexData(const void* input, size_t stride, size_t count, void* output) -{ - const unsigned int outputComponentSize = toFloat ? 4 : 2; - const unsigned int componentCount = 4; - - const unsigned int rgbMask = 0x3FF; // 1 set in bits 0 through 9 - const unsigned int redShift = 0; // red is bits 0 through 9 - const unsigned int greenShift = 10; // green is bits 10 through 19 - const unsigned int blueShift = 20; // blue is bits 20 through 29 - - const unsigned int alphaMask = 0x3; // 1 set in bits 0 and 1 - const unsigned int alphaShift = 30; // Alpha is the 30 and 31 bits - - for (unsigned int i = 0; i < count; i++) - { - GLuint packedValue = *reinterpret_cast(reinterpret_cast(input) + (i * stride)); - GLbyte *offsetOutput = reinterpret_cast(output) + (i * outputComponentSize * componentCount); - - copyPackedRGB( (packedValue >> redShift) & rgbMask, offsetOutput + (0 * outputComponentSize)); - copyPackedRGB( (packedValue >> greenShift) & rgbMask, offsetOutput + (1 * outputComponentSize)); - copyPackedRGB( (packedValue >> blueShift) & rgbMask, offsetOutput + (2 * outputComponentSize)); - copyPackedAlpha((packedValue >> alphaShift) & alphaMask, offsetOutput + (3* outputComponentSize)); - } -} +#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 new file mode 100644 index 0000000000..7eef17b22b --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.inl @@ -0,0 +1,288 @@ +// +// 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 index 08457af76d..a34ef03fb8 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright 2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -8,9 +7,9 @@ // BufferD3D.cpp Defines common functionality between the Buffer9 and Buffer11 classes. #include "libGLESv2/renderer/d3d/BufferD3D.h" -#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/renderer/d3d/VertexBuffer.h" #include "libGLESv2/renderer/d3d/IndexBuffer.h" +#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/main.h" namespace rx diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h index 8e204b9139..44f14cee58 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h @@ -11,7 +11,6 @@ #include "libGLESv2/renderer/BufferImpl.h" #include "libGLESv2/angletypes.h" -#include "libGLESv2/renderer/IndexRangeCache.h" namespace rx { @@ -31,13 +30,11 @@ class BufferD3D : public BufferImpl unsigned int getSerial() const { return mSerial; } virtual size_t getSize() const = 0; - virtual void clear() = 0; virtual bool supportsDirectBinding() const = 0; virtual Renderer* getRenderer() = 0; rx::StaticVertexBufferInterface *getStaticVertexBuffer() { return mStaticVertexBuffer; } rx::StaticIndexBufferInterface *getStaticIndexBuffer() { return mStaticIndexBuffer; } - rx::IndexRangeCache *getIndexRangeCache() { return &mIndexRangeCache; } void initializeStaticData(); void invalidateStaticData(); @@ -51,7 +48,6 @@ class BufferD3D : public BufferImpl rx::StaticVertexBufferInterface *mStaticVertexBuffer; rx::StaticIndexBufferInterface *mStaticIndexBuffer; - rx::IndexRangeCache mIndexRangeCache; unsigned int mUnmodifiedDataUse; }; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp new file mode 100644 index 0000000000..13411ebe64 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp @@ -0,0 +1,1144 @@ +// +// 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/Renderer.h" +#include "libGLESv2/Shader.h" +#include "libGLESv2/Program.h" +#include "libGLESv2/ProgramBinary.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 +{ + +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 rx::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]; +} + +} + +namespace rx +{ + +const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@"; +const std::string PIXEL_OUTPUT_STUB_STRING = "@@ PIXEL OUTPUT @@"; + +DynamicHLSL::DynamicHLSL(rx::Renderer *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, rx::ShaderD3D *fragmentShader, + rx::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 (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 && transformFeedbackVarying != "gl_Position" && transformFeedbackVarying != "gl_PointSize") + { + 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) & rx::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 rx::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(InfoLog &infoLog, int registers, const VaryingPacking packing, + std::string& pixelHLSL, std::string& vertexHLSL, + rx::ShaderD3D *fragmentShader, rx::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(); + + // TODO (geofflang): Use context's caps + const int maxVaryingVectors = mRenderer->getRendererCaps().maxVaryingVectors; + + 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 && mRenderer->getCurrentClientVersion() < 3); + const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getRendererCaps().maxDrawBuffers : 1); + + int shaderVersion = vertexShader->getShaderVersion(); + + if (registersNeeded > 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 * mRenderer->getRendererCaps().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 * mRenderer->getRendererCaps().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(rx::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, rx::ShaderD3D *fragmentShader, rx::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, rx::ShaderD3D *fragmentShader, rx::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) & rx::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 new file mode 100644 index 0000000000..f68ed98401 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h @@ -0,0 +1,104 @@ +// +// 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 rx +{ +class Renderer; +} + +namespace sh +{ +struct Attribute; +struct ShaderVariable; +} + +namespace gl +{ +class InfoLog; +struct VariableLocation; +struct LinkedVarying; +struct VertexAttribute; +struct VertexFormat; +struct PackedVarying; +} + +namespace rx +{ +class Renderer; +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(rx::Renderer *const renderer); + + int packVaryings(gl::InfoLog &infoLog, VaryingPacking packing, rx::ShaderD3D *fragmentShader, + rx::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(gl::InfoLog &infoLog, int registers, const VaryingPacking packing, + std::string& pixelHLSL, std::string& vertexHLSL, + rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader, + const std::vector& transformFeedbackVaryings, + std::vector *linkedVaryings, + std::map *programOutputVars, + std::vector *outPixelShaderKey, + bool *outUsesFragDepth) const; + + std::string generateGeometryShaderHLSL(int registers, rx::ShaderD3D *fragmentShader, rx::ShaderD3D *vertexShader) const; + void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const; + + private: + DISALLOW_COPY_AND_ASSIGN(DynamicHLSL); + + rx::Renderer *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 rx::ShaderD3D *vertexShader, std::vector *linkedVaryings) const; + void storeBuiltinLinkedVaryings(const SemanticInfo &info, std::vector *linkedVaryings) const; + void defineOutputVariables(rx::ShaderD3D *fragmentShader, std::map *programOutputVars) const; + std::string generatePointSpriteHLSL(int registers, rx::ShaderD3D *fragmentShader, rx::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 index e3b88d506d..d0131974ee 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp @@ -1,4 +1,9 @@ -#include "precompiled.h" +// +// 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" @@ -6,10 +11,6 @@ #include "common/utilities.h" #include "common/platform.h" -#include "third_party/trace_event/trace_event.h" - -#include - #if defined(__MINGW32__) && !defined(D3DCOMPILER_DLL) // Add define + typedefs for older MinGW-w64 headers (pre 5783) @@ -29,10 +30,6 @@ typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const #define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL #endif -#ifndef LoadLibrary -#define LoadLibrary(dll) LoadPackagedLibrary(dll, NULL) -#endif - namespace rx { @@ -49,7 +46,6 @@ HLSLCompiler::~HLSLCompiler() bool HLSLCompiler::initialize() { - TRACE_EVENT0("gpu", "initializeCompiler"); #if !defined(ANGLE_PLATFORM_WINRT) #if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. @@ -153,14 +149,11 @@ ShaderBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const char *hlsl return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*)NULL); } - infoLog.append("Warning: D3D shader compilation failed with "); - infoLog.append(flagNames[i]); - infoLog.append(" flags."); + infoLog.append("Warning: D3D shader compilation failed with %s flags.", flagNames[i]); + if (i + 1 < attempts) { - infoLog.append(" Retrying with "); - infoLog.append(flagNames[i + 1]); - infoLog.append(".\n"); + infoLog.append(" Retrying with %s.\n", flagNames[i + 1]); } } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp index 615d11a1f1..0854b968da 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h index 242ce5af70..60a6ffdf37 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h @@ -21,10 +21,7 @@ class Framebuffer; namespace rx { -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; -class TextureStorageInterface3D; -class TextureStorageInterface2DArray; +class TextureStorage; class ImageD3D : public Image { @@ -36,14 +33,14 @@ class ImageD3D : public Image virtual bool isDirty() const = 0; - virtual void setManagedSurface(TextureStorageInterface2D *storage, int level) {}; - virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level) {}; - virtual void setManagedSurface(TextureStorageInterface3D *storage, int level) {}; - virtual void setManagedSurface(TextureStorageInterface2DArray *storage, int layer, int level) {}; - virtual bool copyToStorage(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; - virtual bool copyToStorage(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; - virtual bool copyToStorage(TextureStorageInterface3D *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) = 0; - virtual bool copyToStorage(TextureStorageInterface2DArray *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height) = 0; + virtual void setManagedSurface2D(TextureStorage *storage, int level) {}; + virtual void setManagedSurfaceCube(TextureStorage *storage, int face, int level) {}; + virtual void setManagedSurface3D(TextureStorage *storage, int level) {}; + virtual void setManagedSurface2DArray(TextureStorage *storage, int layer, int level) {}; + virtual bool copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; + virtual bool copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; + virtual bool copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) = 0; + virtual bool copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height) = 0; private: DISALLOW_COPY_AND_ASSIGN(ImageD3D); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp index 13e35e09ec..1dce1270d8 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -67,21 +66,22 @@ unsigned int IndexBufferInterface::getSerial() const return mIndexBuffer->getSerial(); } -bool IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset) +gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset) { // Protect against integer overflow if (mWritePosition + size < mWritePosition) { - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Mapping of internal index buffer would cause an integer overflow."); } - if (!mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory)) + gl::Error error = mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory); + if (error.isError()) { if (outMappedMemory) { *outMappedMemory = NULL; } - return false; + return error; } if (streamOffset) @@ -90,10 +90,10 @@ bool IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory, } mWritePosition += size; - return true; + return gl::Error(GL_NO_ERROR); } -bool IndexBufferInterface::unmapBuffer() +gl::Error IndexBufferInterface::unmapBuffer() { return mIndexBuffer->unmapBuffer(); } @@ -113,12 +113,12 @@ void IndexBufferInterface::setWritePosition(unsigned int writePosition) mWritePosition = writePosition; } -bool IndexBufferInterface::discard() +gl::Error IndexBufferInterface::discard() { return mIndexBuffer->discard(); } -bool IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType) +gl::Error IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType) { if (mIndexBuffer->getBufferSize() == 0) { @@ -138,26 +138,30 @@ StreamingIndexBufferInterface::~StreamingIndexBufferInterface() { } -bool StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType) +gl::Error StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType) { - bool result = true; unsigned int curBufferSize = getBufferSize(); unsigned int writePos = getWritePosition(); if (size > curBufferSize) { - result = setBufferSize(std::max(size, 2 * curBufferSize), indexType); + 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) { - if (!discard()) + gl::Error error = discard(); + if (error.isError()) { - return false; + return error; } setWritePosition(0); } - return result; + return gl::Error(GL_NO_ERROR); } @@ -169,7 +173,7 @@ StaticIndexBufferInterface::~StaticIndexBufferInterface() { } -bool StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType) +gl::Error StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType) { unsigned int curSize = getBufferSize(); if (curSize == 0) @@ -178,13 +182,12 @@ bool StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum in } else if (curSize >= size && indexType == getIndexType()) { - return true; + return gl::Error(GL_NO_ERROR); } else { - ERR("Static index buffers can't be resized"); UNREACHABLE(); - return false; + return gl::Error(GL_INVALID_OPERATION, "Internal static index buffers can't be resized"); } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h index 6fb885a1cd..1bb5ae2c4a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h @@ -11,6 +11,7 @@ #define LIBGLESV2_RENDERER_INDEXBUFFER_H_ #include "common/angleutils.h" +#include "libGLESv2/Error.h" #include "libGLESv2/renderer/IndexRangeCache.h" namespace rx @@ -23,16 +24,16 @@ class IndexBuffer IndexBuffer(); virtual ~IndexBuffer(); - virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) = 0; + virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) = 0; - virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) = 0; - virtual bool unmapBuffer() = 0; + virtual gl::Error mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) = 0; + virtual gl::Error unmapBuffer() = 0; - virtual bool discard() = 0; + virtual gl::Error discard() = 0; virtual GLenum getIndexType() const = 0; virtual unsigned int getBufferSize() const = 0; - virtual bool setSize(unsigned int bufferSize, GLenum indexType) = 0; + virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType) = 0; unsigned int getSerial() const; @@ -52,15 +53,15 @@ class IndexBufferInterface IndexBufferInterface(Renderer *renderer, bool dynamic); virtual ~IndexBufferInterface(); - virtual bool reserveBufferSpace(unsigned int size, GLenum indexType) = 0; + virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) = 0; GLenum getIndexType() const; unsigned int getBufferSize() const; unsigned int getSerial() const; - bool mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset); - bool unmapBuffer(); + gl::Error mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset); + gl::Error unmapBuffer(); IndexBuffer *getIndexBuffer() const; @@ -68,9 +69,9 @@ class IndexBufferInterface unsigned int getWritePosition() const; void setWritePosition(unsigned int writePosition); - bool discard(); + gl::Error discard(); - bool setBufferSize(unsigned int bufferSize, GLenum indexType); + gl::Error setBufferSize(unsigned int bufferSize, GLenum indexType); private: DISALLOW_COPY_AND_ASSIGN(IndexBufferInterface); @@ -89,7 +90,7 @@ class StreamingIndexBufferInterface : public IndexBufferInterface StreamingIndexBufferInterface(Renderer *renderer); ~StreamingIndexBufferInterface(); - virtual bool reserveBufferSpace(unsigned int size, GLenum indexType); + virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType); }; class StaticIndexBufferInterface : public IndexBufferInterface @@ -98,7 +99,7 @@ class StaticIndexBufferInterface : public IndexBufferInterface explicit StaticIndexBufferInterface(Renderer *renderer); ~StaticIndexBufferInterface(); - virtual bool reserveBufferSpace(unsigned int size, GLenum indexType); + virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType); IndexRangeCache *getIndexRangeCache(); @@ -108,4 +109,4 @@ class StaticIndexBufferInterface : public IndexBufferInterface } -#endif // LIBGLESV2_RENDERER_INDEXBUFFER_H_ \ No newline at end of file +#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 index 932524c132..8d455b4bf3 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp @@ -1,6 +1,5 @@ -#include "precompiled.h" // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -10,54 +9,20 @@ #include "libGLESv2/renderer/d3d/IndexDataManager.h" #include "libGLESv2/renderer/d3d/BufferD3D.h" - +#include "libGLESv2/renderer/d3d/IndexBuffer.h" +#include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/main.h" #include "libGLESv2/formatutils.h" -#include "libGLESv2/renderer/d3d/IndexBuffer.h" namespace rx { -IndexDataManager::IndexDataManager(Renderer *renderer) : mRenderer(renderer) +static void ConvertIndices(GLenum sourceType, GLenum destinationType, const void *input, GLsizei count, void *output) { - mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer); - if (!mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT)) - { - delete mStreamingBufferShort; - mStreamingBufferShort = NULL; - } - - mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer); - if (!mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) - { - delete mStreamingBufferInt; - mStreamingBufferInt = NULL; - } - - if (!mStreamingBufferShort) - { - // Make sure both buffers are deleted. - delete mStreamingBufferInt; - mStreamingBufferInt = NULL; - - ERR("Failed to allocate the streaming index buffer(s)."); - } - - mCountingBuffer = NULL; -} - -IndexDataManager::~IndexDataManager() -{ - delete mStreamingBufferShort; - delete mStreamingBufferInt; - delete mCountingBuffer; -} - -static void convertIndices(GLenum type, const void *input, GLsizei count, void *output) -{ - if (type == GL_UNSIGNED_BYTE) + if (sourceType == GL_UNSIGNED_BYTE) { + ASSERT(destinationType == GL_UNSIGNED_SHORT); const GLubyte *in = static_cast(input); GLushort *out = static_cast(output); @@ -66,55 +31,51 @@ static void convertIndices(GLenum type, const void *input, GLsizei count, void * out[i] = in[i]; } } - else if (type == GL_UNSIGNED_INT) + else if (sourceType == GL_UNSIGNED_INT) { + ASSERT(destinationType == GL_UNSIGNED_INT); memcpy(output, input, count * sizeof(GLuint)); } - else if (type == GL_UNSIGNED_SHORT) + else if (sourceType == GL_UNSIGNED_SHORT) { - memcpy(output, input, count * sizeof(GLushort)); + 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(); } -template -static void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +IndexDataManager::IndexDataManager(Renderer *renderer) + : mRenderer(renderer), + mStreamingBufferShort(NULL), + mStreamingBufferInt(NULL) { - *minIndex = indices[0]; - *maxIndex = indices[0]; - - for (GLsizei i = 0; i < count; i++) - { - if (*minIndex > indices[i]) *minIndex = indices[i]; - if (*maxIndex < indices[i]) *maxIndex = indices[i]; - } } -static void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +IndexDataManager::~IndexDataManager() { - if (type == GL_UNSIGNED_BYTE) - { - computeRange(static_cast(indices), count, minIndex, maxIndex); - } - else if (type == GL_UNSIGNED_INT) - { - computeRange(static_cast(indices), count, minIndex, maxIndex); - } - else if (type == GL_UNSIGNED_SHORT) - { - computeRange(static_cast(indices), count, minIndex, maxIndex); - } - else UNREACHABLE(); + SafeDelete(mStreamingBufferShort); + SafeDelete(mStreamingBufferInt); } -GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated) +gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated) { - if (!mStreamingBufferShort) - { - return GL_OUT_OF_MEMORY; - } + 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; @@ -122,10 +83,6 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer if (buffer != NULL) { - if (reinterpret_cast(indices) > std::numeric_limits::max()) - { - return GL_OUT_OF_MEMORY; - } offset = static_cast(reinterpret_cast(indices)); storage = BufferD3D::makeBufferD3D(buffer->getImplementation()); @@ -138,59 +95,56 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer default: UNREACHABLE(); alignedOffset = false; } - unsigned int typeSize = gl::GetTypeBytes(type); - - // check for integer overflows - if (static_cast(count) > (std::numeric_limits::max() / typeSize) || - typeSize * static_cast(count) + offset < offset) - { - return GL_OUT_OF_MEMORY; - } - - if (typeSize * static_cast(count) + offset > storage->getSize()) - { - return GL_INVALID_OPERATION; - } + ASSERT(typeInfo.bytes * static_cast(count) + offset <= storage->getSize()); indices = static_cast(storage->getData()) + offset; } - StreamingIndexBufferInterface *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort; - StaticIndexBufferInterface *staticBuffer = storage ? storage->getStaticIndexBuffer() : NULL; - IndexBufferInterface *indexBuffer = streamingBuffer; + IndexBufferInterface *indexBuffer = NULL; bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() && destinationIndexType == type; unsigned int streamOffset = 0; if (directStorage) { - indexBuffer = streamingBuffer; streamOffset = offset; - if (!storage->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex, - &translated->maxIndex, NULL)) + if (!buffer->getIndexRangeCache()->findRange(type, offset, count, NULL, NULL)) { - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - storage->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, - translated->maxIndex, offset); + 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, &translated->minIndex, - &translated->maxIndex, &streamOffset)) + if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, NULL, &streamOffset)) { - streamOffset = (offset / gl::GetTypeBytes(type)) * gl::GetTypeBytes(destinationIndexType); - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, - translated->maxIndex, streamOffset); + streamOffset = (offset / typeInfo.bytes) * gl::GetTypeInfo(destinationIndexType).bytes; + staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, streamOffset); } } - else + + // 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) @@ -198,7 +152,7 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer if (staticBuffer->getBufferSize() == 0 && alignedOffset) { indexBuffer = staticBuffer; - convertCount = storage->getSize() / gl::GetTypeBytes(type); + convertCount = storage->getSize() / typeInfo.bytes; } else { @@ -207,133 +161,95 @@ GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer } } - if (!indexBuffer) - { - ERR("No valid index buffer."); - return GL_INVALID_OPERATION; - } + ASSERT(indexBuffer); - unsigned int indexTypeSize = gl::GetTypeBytes(destinationIndexType); - if (convertCount > std::numeric_limits::max() / indexTypeSize) + if (convertCount > std::numeric_limits::max() / destTypeInfo.bytes) { - ERR("Reserving %u indicies of %u bytes each exceeds the maximum buffer size.", convertCount, indexTypeSize); - return GL_OUT_OF_MEMORY; + 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 * indexTypeSize; - if (!indexBuffer->reserveBufferSpace(bufferSizeRequired, type)) + unsigned int bufferSizeRequired = convertCount * destTypeInfo.bytes; + error = indexBuffer->reserveBufferSpace(bufferSizeRequired, type); + if (error.isError()) { - ERR("Failed to reserve %u bytes in an index buffer.", bufferSizeRequired); - return GL_OUT_OF_MEMORY; + return error; } void* output = NULL; - if (!indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset)) + error = indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset); + if (error.isError()) { - ERR("Failed to map index buffer."); - return GL_OUT_OF_MEMORY; + return error; } - convertIndices(type, staticBuffer ? storage->getData() : indices, convertCount, output); + ConvertIndices(type, destinationIndexType, staticBuffer ? storage->getData() : indices, convertCount, output); - if (!indexBuffer->unmapBuffer()) + error = indexBuffer->unmapBuffer(); + if (error.isError()) { - ERR("Failed to unmap index buffer."); - return GL_OUT_OF_MEMORY; + return error; } - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - if (staticBuffer) { - streamOffset = (offset / gl::GetTypeBytes(type)) * gl::GetTypeBytes(destinationIndexType); - staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, - translated->maxIndex, streamOffset); + streamOffset = (offset / typeInfo.bytes) * destTypeInfo.bytes; + staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, streamOffset); } } translated->storage = directStorage ? storage : NULL; - translated->indexBuffer = indexBuffer->getIndexBuffer(); + translated->indexBuffer = indexBuffer ? indexBuffer->getIndexBuffer() : NULL; translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial(); - translated->startIndex = streamOffset / gl::GetTypeBytes(destinationIndexType); + translated->startIndex = streamOffset / destTypeInfo.bytes; translated->startOffset = streamOffset; + translated->indexType = destinationIndexType; if (storage) { - storage->promoteStaticUsage(count * gl::GetTypeBytes(type)); + storage->promoteStaticUsage(count * typeInfo.bytes); } - return GL_NO_ERROR; + return gl::Error(GL_NO_ERROR); } -StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count) +gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType, IndexBufferInterface **outBuffer) { - if (count <= 65536) // 16-bit indices + ASSERT(outBuffer); + if (destinationIndexType == GL_UNSIGNED_INT) { - const unsigned int spaceNeeded = count * sizeof(unsigned short); - - if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded) + if (!mStreamingBufferInt) { - delete mCountingBuffer; - mCountingBuffer = new StaticIndexBufferInterface(mRenderer); - mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); - - void* mappedMemory = NULL; - if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL)) - { - ERR("Failed to map counting buffer."); - return NULL; - } - - unsigned short *data = reinterpret_cast(mappedMemory); - for(int i = 0; i < count; i++) + mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer); + gl::Error error = mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + if (error.isError()) { - data[i] = i; - } - - if (!mCountingBuffer->unmapBuffer()) - { - ERR("Failed to unmap counting buffer."); - return NULL; + SafeDelete(mStreamingBufferInt); + return error; } } + + *outBuffer = mStreamingBufferInt; + return gl::Error(GL_NO_ERROR); } - else if (mStreamingBufferInt) // 32-bit indices supported + else { - const unsigned int spaceNeeded = count * sizeof(unsigned int); + ASSERT(destinationIndexType == GL_UNSIGNED_SHORT); - if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded) + if (!mStreamingBufferShort) { - delete mCountingBuffer; - mCountingBuffer = new StaticIndexBufferInterface(mRenderer); - mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); - - void* mappedMemory = NULL; - if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL)) + mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer); + gl::Error error = mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT); + if (error.isError()) { - ERR("Failed to map counting buffer."); - return NULL; - } - - unsigned int *data = reinterpret_cast(mappedMemory); - for(int i = 0; i < count; i++) - { - data[i] = i; - } - - if (!mCountingBuffer->unmapBuffer()) - { - ERR("Failed to unmap counting buffer."); - return NULL; + SafeDelete(mStreamingBufferShort); + return error; } } - } - else - { - return NULL; - } - return mCountingBuffer; + *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 index 8f981936ea..6d0b89e6d4 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -11,6 +11,10 @@ #define LIBGLESV2_INDEXDATAMANAGER_H_ #include "common/angleutils.h" +#include "common/mathutil.h" +#include "libGLESv2/Error.h" + +#include namespace { @@ -24,6 +28,7 @@ class Buffer; namespace rx { +class IndexBufferInterface; class StaticIndexBufferInterface; class StreamingIndexBufferInterface; class IndexBuffer; @@ -32,13 +37,13 @@ class Renderer; struct TranslatedIndexData { - unsigned int minIndex; - unsigned int maxIndex; + RangeUI indexRange; unsigned int startIndex; unsigned int startOffset; // In bytes IndexBuffer *indexBuffer; BufferD3D *storage; + GLenum indexType; unsigned int serial; }; @@ -48,17 +53,17 @@ class IndexDataManager explicit IndexDataManager(Renderer *renderer); virtual ~IndexDataManager(); - GLenum prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated); - StaticIndexBufferInterface *getCountingIndices(GLsizei count); + 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); Renderer *const mRenderer; StreamingIndexBufferInterface *mStreamingBufferShort; StreamingIndexBufferInterface *mStreamingBufferInt; - StaticIndexBufferInterface *mCountingBuffer; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp index 301bbe8d3d..2b5b09a324 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp @@ -5,6 +5,7 @@ // #include "libGLESv2/renderer/d3d/MemoryBuffer.h" +#include "common/debug.h" #include #include @@ -66,6 +67,7 @@ const uint8_t *MemoryBuffer::data() const 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 index 2484c07455..c65f79fe10 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h @@ -21,6 +21,7 @@ class MemoryBuffer bool resize(size_t size); size_t size() const; + bool empty() const { return mSize == 0; } const uint8_t *data() const; uint8_t *data(); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp new file mode 100644 index 0000000000..d7d97cc2bd --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp @@ -0,0 +1,205 @@ +// +// 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/utilities.h" +#include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/ShaderExecutable.h" +#include "libGLESv2/renderer/d3d/DynamicHLSL.h" +#include "libGLESv2/renderer/d3d/ShaderD3D.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +ProgramD3D::ProgramD3D(rx::Renderer *renderer) + : ProgramImpl(), + mRenderer(renderer), + mDynamicHLSL(NULL), + mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE), + mPixelWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE), + mVertexUniformStorage(NULL), + mFragmentUniformStorage(NULL) +{ + mDynamicHLSL = new rx::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::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) +{ + stream->readString(&mVertexHLSL); + stream->readInt(&mVertexWorkarounds); + stream->readString(&mPixelHLSL); + stream->readInt(&mPixelWorkarounds); + stream->readBool(&mUsesFragDepth); + + 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); + } + + return true; +} + +bool ProgramD3D::save(gl::BinaryOutputStream *stream) +{ + stream->writeString(mVertexHLSL); + stream->writeInt(mVertexWorkarounds); + stream->writeString(mPixelHLSL); + stream->writeInt(mPixelWorkarounds); + stream->writeInt(mUsesFragDepth); + + const std::vector &pixelShaderKey = mPixelShaderKey; + stream->writeInt(pixelShaderKey.size()); + for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKey.size(); pixelShaderKeyIndex++) + { + const rx::PixelShaderOutputVariable &variable = pixelShaderKey[pixelShaderKeyIndex]; + stream->writeInt(variable.type); + stream->writeString(variable.name); + stream->writeString(variable.source); + stream->writeInt(variable.outputIndex); + } + + return true; +} + +rx::ShaderExecutable *ProgramD3D::getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector &outputSignature, + const std::vector &transformFeedbackLinkedVaryings, + bool separatedOutputBuffers) +{ + std::string finalPixelHLSL = mDynamicHLSL->generatePixelShaderForOutputSignature(mPixelHLSL, mPixelShaderKey, mUsesFragDepth, + outputSignature); + + // Generate new pixel executable + rx::ShaderExecutable *pixelExecutable = mRenderer->compileToExecutable(infoLog, finalPixelHLSL.c_str(), rx::SHADER_PIXEL, + transformFeedbackLinkedVaryings, separatedOutputBuffers, + mPixelWorkarounds); + + return pixelExecutable; +} + +rx::ShaderExecutable *ProgramD3D::getVertexExecutableForInputLayout(gl::InfoLog &infoLog, + const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], + const sh::Attribute shaderAttributes[], + const std::vector &transformFeedbackLinkedVaryings, + bool separatedOutputBuffers) +{ + // Generate new dynamic layout with attribute conversions + std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, shaderAttributes); + + // Generate new vertex executable + rx::ShaderExecutable *vertexExecutable = mRenderer->compileToExecutable(infoLog, finalVertexHLSL.c_str(), + rx::SHADER_VERTEX, + transformFeedbackLinkedVaryings, separatedOutputBuffers, + mVertexWorkarounds); + + return vertexExecutable; +} + +bool ProgramD3D::link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, + const std::vector &transformFeedbackVaryings, int *registers, + std::vector *linkedVaryings, std::map *outputVariables) +{ + rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation()); + rx::ShaderD3D *fragmentShaderD3D = rx::ShaderD3D::makeShaderD3D(fragmentShader->getImplementation()); + + mPixelHLSL = fragmentShaderD3D->getTranslatedSource(); + mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds(); + + mVertexHLSL = vertexShaderD3D->getTranslatedSource(); + mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds(); + + // Map the varyings to the register file + rx::VaryingPacking packing = { NULL }; + *registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings); + + if (*registers < 0) + { + return false; + } + + if (!gl::ProgramBinary::linkVaryings(infoLog, fragmentShader, vertexShader)) + { + return false; + } + + if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, *registers, packing, mPixelHLSL, mVertexHLSL, + fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings, + linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth)) + { + return false; + } + + return true; +} + +void ProgramD3D::initializeUniformStorage(const std::vector &uniforms) +{ + // Compute total default block size + unsigned int vertexRegisters = 0; + unsigned int fragmentRegisters = 0; + for (size_t uniformIndex = 0; uniformIndex < uniforms.size(); uniformIndex++) + { + const gl::LinkedUniform &uniform = *uniforms[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); +} + +void ProgramD3D::reset() +{ + mVertexHLSL.clear(); + mVertexWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE; + + mPixelHLSL.clear(); + mPixelWorkarounds = rx::ANGLE_D3D_WORKAROUND_NONE; + mUsesFragDepth = false; + mPixelShaderKey.clear(); + + SafeDelete(mVertexUniformStorage); + SafeDelete(mFragmentUniformStorage); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h new file mode 100644 index 0000000000..d645c57daa --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h @@ -0,0 +1,87 @@ +// +// 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 +#include + +namespace gl +{ +struct LinkedUniform; +struct VariableLocation; +struct VertexFormat; +} + +namespace rx +{ + +class UniformStorage; + +class ProgramD3D : public ProgramImpl +{ + public: + ProgramD3D(rx::Renderer *renderer); + virtual ~ProgramD3D(); + + static ProgramD3D *makeProgramD3D(ProgramImpl *impl); + static const ProgramD3D *makeProgramD3D(const ProgramImpl *impl); + + Renderer *getRenderer() { return mRenderer; } + DynamicHLSL *getDynamicHLSL() { return mDynamicHLSL; } + const std::vector &getPixelShaderKey() { return mPixelShaderKey; } + + GLenum getBinaryFormat() { return GL_PROGRAM_BINARY_ANGLE; } + bool load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream); + bool save(gl::BinaryOutputStream *stream); + + ShaderExecutable *getPixelExecutableForOutputLayout(gl::InfoLog &infoLog, const std::vector &outputSignature, + const std::vector &transformFeedbackLinkedVaryings, + bool separatedOutputBuffers); + ShaderExecutable *getVertexExecutableForInputLayout(gl::InfoLog &infoLog, + const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], + const sh::Attribute shaderAttributes[], + const std::vector &transformFeedbackLinkedVaryings, + bool separatedOutputBuffers); + + bool link(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader, + const std::vector &transformFeedbackVaryings, int *registers, + std::vector *linkedVaryings, std::map *outputVariables); + + // D3D only + void initializeUniformStorage(const std::vector &uniforms); + + const UniformStorage &getVertexUniformStorage() const { return *mVertexUniformStorage; } + const UniformStorage &getFragmentUniformStorage() const { return *mFragmentUniformStorage; } + + void reset(); + + private: + DISALLOW_COPY_AND_ASSIGN(ProgramD3D); + + Renderer *mRenderer; + DynamicHLSL *mDynamicHLSL; + + std::string mVertexHLSL; + rx::D3DWorkaroundType mVertexWorkarounds; + + std::string mPixelHLSL; + rx::D3DWorkaroundType mPixelWorkarounds; + bool mUsesFragDepth; + std::vector mPixelShaderKey; + + UniformStorage *mVertexUniformStorage; + UniformStorage *mFragmentUniformStorage; +}; + +} + +#endif // LIBGLESV2_RENDERER_PROGRAMD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp new file mode 100644 index 0000000000..c472113eba --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp @@ -0,0 +1,457 @@ +// +// 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/renderer/d3d/ShaderD3D.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/Shader.h" +#include "libGLESv2/main.h" + +#include "common/utilities.h" + +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(GLenum type, rx::Renderer *renderer) + : mType(type), + mRenderer(renderer), + mShaderVersion(100) +{ + uncompile(); + initializeCompiler(); +} + +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); +} + +// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler) +void ShaderD3D::initializeCompiler() +{ + if (!mFragmentCompiler) + { + int result = ShInitialize(); + + if (result) + { + ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT; + + ShBuiltInResources resources; + ShInitBuiltInResources(&resources); + + // TODO(geofflang): use context's caps + const gl::Caps &caps = mRenderer->getRendererCaps(); + const gl::Extensions &extensions = mRenderer->getRendererExtensions(); + + 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, SH_GLES2_SPEC, hlslVersion, &resources); + mVertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, SH_GLES2_SPEC, 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(); +} + +void ShaderD3D::compileToHLSL(void *compiler, const std::string &source) +{ + // ensure the compiler is loaded + initializeCompiler(); + + int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES); + std::string sourcePath; + if (gl::perfActive()) + { + sourcePath = getTempPath(); + writeFile(sourcePath.c_str(), source.c_str(), source.length()); + compileOptions |= SH_LINE_DIRECTIVES; + } + + 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); + } + + size_t shaderVersion = 100; + ShGetInfo(compiler, SH_SHADER_VERSION, &shaderVersion); + + mShaderVersion = static_cast(shaderVersion); + + if (shaderVersion == 300 && mRenderer->getCurrentClientVersion() < 3) + { + mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts"; + TRACE("\n%s", mInfoLog.c_str()); + } + else if (result) + { + size_t objCodeLen = 0; + ShGetInfo(compiler, SH_OBJECT_CODE_LENGTH, &objCodeLen); + + char* outputHLSL = new char[objCodeLen]; + ShGetObjectCode(compiler, outputHLSL); + +#ifdef _DEBUG + 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 << outputHLSL; + mHlsl = hlslStream.str(); +#else + mHlsl = outputHLSL; +#endif + + SafeDeleteArray(outputHLSL); + + 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.c_str(), &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.c_str(), &index); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(result); + + mInterfaceBlockRegisterMap[interfaceBlock.name] = index; + } + } + } + else + { + size_t infoLogLen = 0; + ShGetInfo(compiler, SH_INFO_LOG_LENGTH, &infoLogLen); + + char* infoLog = new char[infoLogLen]; + ShGetInfoLog(compiler, infoLog); + mInfoLog = infoLog; + + TRACE("\n%s", mInfoLog.c_str()); + } +} + +rx::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 rx::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 rx::ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION; + } + + return rx::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; + } + + size_t outputType = 0; + ShGetInfo(compiler, SH_OUTPUT_TYPE, &outputType); + + return static_cast(outputType); +} + +bool ShaderD3D::compile(const std::string &source) +{ + uncompile(); + + void *compiler = getCompiler(); + + compileToHLSL(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); + } + } + + 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 new file mode 100644 index 0000000000..40e64cf36c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h @@ -0,0 +1,94 @@ +// +// 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/Shader.h" + +#include + +namespace rx +{ +class DynamicHLSL; +class Renderer; + +class ShaderD3D : public ShaderImpl +{ + friend class DynamicHLSL; + + public: + ShaderD3D(GLenum type, rx::Renderer *renderer); + virtual ~ShaderD3D(); + + static ShaderD3D *makeShaderD3D(ShaderImpl *impl); + static const ShaderD3D *makeShaderD3D(const ShaderImpl *impl); + + // ShaderImpl implementation + const std::string &getInfoLog() const { return mInfoLog; } + const std::string &getTranslatedSource() const { return mHlsl; } + + // 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; + + rx::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 std::string &source); + + private: + DISALLOW_COPY_AND_ASSIGN(ShaderD3D); + + void compileToHLSL(void *compiler, const std::string &source); + void parseVaryings(void *compiler); + + void initializeCompiler(); + 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; + rx::Renderer *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::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 index e725e2fefe..96c84977cb 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright 2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -7,39 +6,25 @@ // TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends. -#include "common/mathutil.h" -#include "common/utilities.h" -#include "libEGL/Surface.h" +#include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/renderer/d3d/TextureStorage.h" +#include "libGLESv2/renderer/d3d/ImageD3D.h" #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/Renderer.h" -#include "libGLESv2/renderer/d3d/ImageD3D.h" -#include "libGLESv2/renderer/d3d/TextureD3D.h" -#include "libGLESv2/renderer/d3d/TextureStorage.h" -namespace rx -{ +#include "libEGL/Surface.h" + +#include "common/mathutil.h" +#include "common/utilities.h" -bool IsMipmapFiltered(const gl::SamplerState &samplerState) +namespace rx { - 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 IsRenderTargetUsage(GLenum usage) { @@ -58,6 +43,26 @@ 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); + + TextureStorage *storage = getBaseLevelStorage(); + if (storage) + { + updateStorage(); + } + + return storage; +} + GLint TextureD3D::getBaseLevelWidth() const { const Image *baseImage = getBaseLevelImage(); @@ -116,7 +121,7 @@ void TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const } bool 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, Image *image) + GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index) { const void *pixelData = pixels; @@ -124,7 +129,7 @@ bool TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei w if (unpack.pixelBuffer.id() != 0) { gl::Buffer *pixelBuffer = unpack.pixelBuffer.get(); - unsigned int offset = reinterpret_cast(pixels); + ptrdiff_t offset = reinterpret_cast(pixels); // TODO: setImage/subImage 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. const void *bufferData = pixelBuffer->getImplementation()->getData(); @@ -133,6 +138,9 @@ bool TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei w if (pixelData != NULL) { + Image *image = getImage(index); + ASSERT(image); + image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment, type, pixelData); mDirtyImages = true; } @@ -178,7 +186,7 @@ bool TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void // to create a render target. ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat)); - unsigned int offset = reinterpret_cast(pixels); + ptrdiff_t offset = reinterpret_cast(pixels); return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea); } @@ -205,7 +213,6 @@ int TextureD3D::mipLevels() const TextureD3D_2D::TextureD3D_2D(Renderer *renderer) : TextureD3D(renderer), - Texture2DImpl(), mTexStorage(NULL) { for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) @@ -216,48 +223,36 @@ TextureD3D_2D::TextureD3D_2D(Renderer *renderer) TextureD3D_2D::~TextureD3D_2D() { - SafeDelete(mTexStorage); - + // 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]; } -} - -TextureD3D_2D *TextureD3D_2D::makeTextureD3D_2D(Texture2DImpl *texture) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureD3D_2D*, texture)); - return static_cast(texture); -} - -TextureStorageInterface *TextureD3D_2D::getNativeTexture() -{ - // ensure the underlying texture is created - initializeStorage(false); - - TextureStorageInterface *storage = getBaseLevelStorage(); - if (storage) - { - updateStorage(); - } - return storage; + SafeDelete(mTexStorage); } -Image *TextureD3D_2D::getImage(int level) const +Image *TextureD3D_2D::getImage(int level, int layer) const { ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(layer == 0); return mImageArray[level]; } -void TextureD3D_2D::setUsage(GLenum usage) +Image *TextureD3D_2D::getImage(const gl::ImageIndex &index) const { - mUsage = usage; + ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(!index.hasLayer()); + ASSERT(index.type == GL_TEXTURE_2D); + return mImageArray[index.mipIndex]; } -void TextureD3D_2D::resetDirty() +GLsizei TextureD3D_2D::getLayerCount(int level) const { - mDirtyImages = false; + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return 1; } GLsizei TextureD3D_2D::getWidth(GLint level) const @@ -294,20 +289,26 @@ GLenum TextureD3D_2D::getActualFormat(GLint level) const bool TextureD3D_2D::isDepth(GLint level) const { - return gl::GetDepthBits(getInternalFormat(level)) > 0; + return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -void TextureD3D_2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +void 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) { - GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat - : gl::GetSizedInternalFormat(format, type); + ASSERT(target == GL_TEXTURE_2D && depth == 1); + + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + bool fastUnpacked = false; + redefineImage(level, sizedInternalFormat, width, height); + // Attempt a fast gpu copy of the pixel data to the surface if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level)) { + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + // Will try to create RT storage if it does not exist - RenderTarget *destRenderTarget = getRenderTarget(level); + RenderTarget *destRenderTarget = getRenderTarget(index); gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1); if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget)) @@ -325,18 +326,26 @@ void TextureD3D_2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum } } -void TextureD3D_2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) +void TextureD3D_2D::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, 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); + TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[level]); } -void TextureD3D_2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +void 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); if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level)) { - RenderTarget *renderTarget = getRenderTarget(level); + RenderTarget *renderTarget = getRenderTarget(index); gl::Box destArea(xoffset, yoffset, 0, width, height, 1); if (renderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget)) @@ -348,22 +357,29 @@ void TextureD3D_2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei } } - if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, mImageArray[level])) + if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, index)) { commitRect(level, xoffset, yoffset, width, height); } } -void TextureD3D_2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) +void TextureD3D_2D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) { + ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0); + if (TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[level])) { commitRect(level, xoffset, yoffset, width, height); } } -void TextureD3D_2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +void 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); + if (!mImageArray[level]->isRenderableFormat()) { mImageArray[level]->copy(0, 0, 0, x, y, width, height, source); @@ -382,13 +398,15 @@ void TextureD3D_2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsi sourceRect.y = y; sourceRect.height = height; - mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, level); + mRenderer->copyImage2D(source, sourceRect, format, 0, 0, mTexStorage, level); } } } void 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) bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0); @@ -412,15 +430,17 @@ void TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLin sourceRect.y = y; sourceRect.height = height; - mRenderer->copyImage(source, sourceRect, - gl::GetFormat(getBaseLevelInternalFormat()), - xoffset, yoffset, mTexStorage, level); + mRenderer->copyImage2D(source, sourceRect, + gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + xoffset, yoffset, mTexStorage, level); } } } -void TextureD3D_2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +void 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); @@ -435,75 +455,9 @@ void TextureD3D_2D::storage(GLsizei levels, GLenum internalformat, GLsizei width mImmutable = true; - setCompleteTexStorage(new TextureStorageInterface2D(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, levels)); -} - -// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85. -bool TextureD3D_2D::isSamplerComplete(const gl::SamplerState &samplerState) const -{ - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - - if (width <= 0 || height <= 0) - { - return false; - } - - if (!mRenderer->getRendererTextureCaps().get(getInternalFormat(0)).filterable) - { - if (samplerState.magFilter != GL_NEAREST || - (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) - { - return false; - } - } - - // TODO(geofflang): use context's extensions - bool npotSupport = mRenderer->getRendererExtensions().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. - if (gl::GetDepthBits(getInternalFormat(0)) > 0 && mRenderer->getCurrentClientVersion() > 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 renderTarget = IsRenderTargetUsage(mUsage); + TextureStorage *storage = mRenderer->createTextureStorage2D(internalformat, renderTarget, width, height, levels); + setCompleteTexStorage(storage); } void TextureD3D_2D::bindTexImage(egl::Surface *surface) @@ -516,7 +470,8 @@ void TextureD3D_2D::bindTexImage(egl::Surface *surface) { SafeDelete(mTexStorage); } - mTexStorage = new TextureStorageInterface2D(mRenderer, surface->getSwapChain()); + + mTexStorage = mRenderer->createTextureStorage2D(surface->getSwapChain()); mDirtyImages = true; } @@ -536,14 +491,20 @@ void TextureD3D_2D::releaseTexImage() void TextureD3D_2D::generateMipmaps() { + // 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)); + } if (mTexStorage && mTexStorage->isRenderTarget()) { + mTexStorage->generateMipmaps(); for (int level = 1; level < levelCount; level++) { - mTexStorage->generateMipmap(level); - mImageArray[level]->markClean(); } } @@ -556,63 +517,24 @@ void TextureD3D_2D::generateMipmaps() } } -unsigned int TextureD3D_2D::getRenderTargetSerial(GLint level) +unsigned int TextureD3D_2D::getRenderTargetSerial(const gl::ImageIndex &index) { - return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level) : 0); + ASSERT(!index.hasLayer()); + return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(index) : 0); } -RenderTarget *TextureD3D_2D::getRenderTarget(GLint level) +RenderTarget *TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index) { - // ensure the underlying texture is created - if (!ensureRenderTarget()) - { - return NULL; - } - - updateStorageLevel(level); + ASSERT(!index.hasLayer()); - // ensure this is NOT a depth texture - if (isDepth(level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(level); -} - -RenderTarget *TextureD3D_2D::getDepthSencil(GLint level) -{ // ensure the underlying texture is created if (!ensureRenderTarget()) { return NULL; } - updateStorageLevel(level); - - // ensure this is actually a depth texture - if (!isDepth(level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(level); -} - -// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. -bool TextureD3D_2D::isMipmapComplete() const -{ - int levelCount = mipLevels(); - - for (int level = 0; level < levelCount; level++) - { - if (!isLevelComplete(level)) - { - return false; - } - } - - return true; + updateStorageLevel(index.mipIndex); + return mTexStorage->getRenderTarget(index); } bool TextureD3D_2D::isValidLevel(int level) const @@ -688,20 +610,21 @@ void TextureD3D_2D::initializeStorage(bool renderTarget) updateStorage(); } -TextureStorageInterface2D *TextureD3D_2D::createCompleteStorage(bool renderTarget) const +TextureStorage *TextureD3D_2D::createCompleteStorage(bool renderTarget) 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)); - return new TextureStorageInterface2D(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, levels); + return mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels); } -void TextureD3D_2D::setCompleteTexStorage(TextureStorageInterface2D *newCompleteTexStorage) +void TextureD3D_2D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) { SafeDelete(mTexStorage); mTexStorage = newCompleteTexStorage; @@ -710,7 +633,7 @@ void TextureD3D_2D::setCompleteTexStorage(TextureStorageInterface2D *newComplete { for (int level = 0; level < mTexStorage->getLevelCount(); level++) { - mImageArray[level]->setManagedSurface(mTexStorage, level); + mImageArray[level]->setManagedSurface2D(mTexStorage, level); } } @@ -739,9 +662,9 @@ bool TextureD3D_2D::ensureRenderTarget() ASSERT(mTexStorage); if (!mTexStorage->isRenderTarget()) { - TextureStorageInterface2D *newRenderTargetStorage = createCompleteStorage(true); + TextureStorage *newRenderTargetStorage = createCompleteStorage(true); - if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) + if (!mRenderer->copyToRenderTarget2D(newRenderTargetStorage, mTexStorage)) { delete newRenderTargetStorage; return gl::error(GL_OUT_OF_MEMORY, false); @@ -754,7 +677,7 @@ bool TextureD3D_2D::ensureRenderTarget() return (mTexStorage && mTexStorage->isRenderTarget()); } -TextureStorageInterface *TextureD3D_2D::getBaseLevelStorage() +TextureStorage *TextureD3D_2D::getBaseLevelStorage() { return mTexStorage; } @@ -809,7 +732,7 @@ void TextureD3D_2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsize if (isValidLevel(level)) { ImageD3D *image = mImageArray[level]; - if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, width, height)) + if (image->copyToStorage2D(mTexStorage, level, xoffset, yoffset, width, height)) { image->markClean(); } @@ -818,8 +741,7 @@ void TextureD3D_2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsize TextureD3D_Cube::TextureD3D_Cube(Renderer *renderer) - : TextureCubeImpl(), - TextureD3D(renderer), + : TextureD3D(renderer), mTexStorage(NULL) { for (int i = 0; i < 6; i++) @@ -833,8 +755,9 @@ TextureD3D_Cube::TextureD3D_Cube(Renderer *renderer) TextureD3D_Cube::~TextureD3D_Cube() { - SafeDelete(mTexStorage); - + // 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) @@ -842,88 +765,86 @@ TextureD3D_Cube::~TextureD3D_Cube() SafeDelete(mImageArray[i][j]); } } -} - -TextureD3D_Cube *TextureD3D_Cube::makeTextureD3D_Cube(TextureCubeImpl *texture) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureD3D_Cube*, texture)); - return static_cast(texture); -} - -TextureStorageInterface *TextureD3D_Cube::getNativeTexture() -{ - // ensure the underlying texture is created - initializeStorage(false); - - TextureStorageInterface *storage = getBaseLevelStorage(); - if (storage) - { - updateStorage(); - } - return storage; + SafeDelete(mTexStorage); } -Image *TextureD3D_Cube::getImage(GLenum target, int level) const +Image *TextureD3D_Cube::getImage(int level, int layer) const { ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - return mImageArray[targetToIndex(target)][level]; + ASSERT(layer < 6); + return mImageArray[layer][level]; } -void TextureD3D_Cube::setUsage(GLenum usage) +Image *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const { - mUsage = usage; + ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(index.layerIndex < 6); + return mImageArray[index.layerIndex][index.mipIndex]; } -void TextureD3D_Cube::resetDirty() +GLsizei TextureD3D_Cube::getLayerCount(int level) const { - mDirtyImages = false; + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return 6; } -GLenum TextureD3D_Cube::getInternalFormat(GLenum target, GLint level) const +GLenum TextureD3D_Cube::getInternalFormat(GLint level, GLint layer) const { if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[targetToIndex(target)][level]->getInternalFormat(); + return mImageArray[layer][level]->getInternalFormat(); else return GL_NONE; } -bool TextureD3D_Cube::isDepth(GLenum target, GLint level) const +bool TextureD3D_Cube::isDepth(GLint level, GLint layer) const { - return gl::GetDepthBits(getInternalFormat(target, level)) > 0; + return gl::GetInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0; } -void TextureD3D_Cube::setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +void 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) { - GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat - : gl::GetSizedInternalFormat(format, type); + ASSERT(depth == 1); + + int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); redefineImage(faceIndex, level, sizedInternalFormat, width, height); TextureD3D::setImage(unpack, type, pixels, mImageArray[faceIndex][level]); } -void TextureD3D_Cube::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) +void TextureD3D_Cube::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, 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 = targetToIndex(target); + int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); + redefineImage(faceIndex, level, format, width, height); TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[faceIndex][level]); } -void TextureD3D_Cube::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +void 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) { - int faceIndex = targetToIndex(target); - if (TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, mImageArray[faceIndex][level])) + ASSERT(depth == 1 && zoffset == 0); + + int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); + + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + if (TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, index)) { commitRect(faceIndex, level, xoffset, yoffset, width, height); } } -void TextureD3D_Cube::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) +void TextureD3D_Cube::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) { - int faceIndex = targetToIndex(target); + ASSERT(depth == 1 && zoffset == 0); + + int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); + if (TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[faceIndex][level])) { commitRect(faceIndex, level, xoffset, yoffset, width, height); @@ -932,9 +853,9 @@ void TextureD3D_Cube::subImageCompressed(GLenum target, GLint level, GLint xoffs void TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) { - int faceIndex = targetToIndex(target); - GLenum sizedInternalFormat = gl::IsSizedInternalFormat(format) ? format - : gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); + int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); + redefineImage(faceIndex, level, sizedInternalFormat, width, height); if (!mImageArray[faceIndex][level]->isRenderableFormat()) @@ -957,14 +878,14 @@ void TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format, GLint sourceRect.y = y; sourceRect.height = height; - mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, target, level); + mRenderer->copyImageCube(source, sourceRect, format, 0, 0, mTexStorage, target, level); } } } void 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 = targetToIndex(target); + int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target); // We can only make our texture storage to a render target if the level we're copying *to* is complete // and the base level is cube-complete. The base level must be cube complete (common case) because we cannot @@ -990,17 +911,20 @@ void TextureD3D_Cube::copySubImage(GLenum target, GLint level, GLint xoffset, GL sourceRect.y = y; sourceRect.height = height; - mRenderer->copyImage(source, sourceRect, gl::GetFormat(getBaseLevelInternalFormat()), - xoffset, yoffset, mTexStorage, target, level); + mRenderer->copyImageCube(source, sourceRect, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + xoffset, yoffset, mTexStorage, target, level); } } } -void TextureD3D_Cube::storage(GLsizei levels, GLenum internalformat, GLsizei size) +void 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, size >> 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); @@ -1017,50 +941,9 @@ void TextureD3D_Cube::storage(GLsizei levels, GLenum internalformat, GLsizei siz mImmutable = true; - setCompleteTexStorage(new TextureStorageInterfaceCube(mRenderer, internalformat, IsRenderTargetUsage(mUsage), size, levels)); -} - -bool TextureD3D_Cube::isSamplerComplete(const gl::SamplerState &samplerState) const -{ - int size = getBaseLevelWidth(); - - bool mipmapping = IsMipmapFiltered(samplerState); - - // TODO(geofflang): use context's texture caps - if (!mRenderer->getRendererTextureCaps().get(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)).filterable) - { - if (samplerState.magFilter != GL_NEAREST || - (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) - { - return false; - } - } - - // TODO(geofflang): use context's extensions - if (!gl::isPow2(size) && !mRenderer->getRendererExtensions().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 (!isMipmapCubeComplete()) // Also tests for isCubeComplete() - { - return false; - } - } - - return true; + bool renderTarget = IsRenderTargetUsage(mUsage); + TextureStorage *storage = mRenderer->createTextureStorageCube(internalformat, renderTarget, width, levels); + setCompleteTexStorage(storage); } // Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. @@ -1090,6 +973,17 @@ bool TextureD3D_Cube::isCubeComplete() const return true; } +void TextureD3D_Cube::bindTexImage(egl::Surface *surface) +{ + UNREACHABLE(); +} + +void TextureD3D_Cube::releaseTexImage() +{ + UNREACHABLE(); +} + + void TextureD3D_Cube::generateMipmaps() { // Purge array levels 1 through q and reset them to represent the generated mipmap levels. @@ -1105,12 +999,12 @@ void TextureD3D_Cube::generateMipmaps() if (mTexStorage && mTexStorage->isRenderTarget()) { + mTexStorage->generateMipmaps(); + for (int faceIndex = 0; faceIndex < 6; faceIndex++) { for (int level = 1; level < levelCount; level++) { - mTexStorage->generateMipmap(faceIndex, level); - mImageArray[faceIndex][level]->markClean(); } } @@ -1127,35 +1021,14 @@ void TextureD3D_Cube::generateMipmaps() } } -unsigned int TextureD3D_Cube::getRenderTargetSerial(GLenum target, GLint level) +unsigned int TextureD3D_Cube::getRenderTargetSerial(const gl::ImageIndex &index) { - return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(target, level) : 0); -} - -RenderTarget *TextureD3D_Cube::getRenderTarget(GLenum target, GLint level) -{ - ASSERT(gl::IsCubemapTextureTarget(target)); - - // ensure the underlying texture is created - if (!ensureRenderTarget()) - { - return NULL; - } - - updateStorageFaceLevel(targetToIndex(target), level); - - // ensure this is NOT a depth texture - if (isDepth(target, level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(target, level); + return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(index) : 0); } -RenderTarget *TextureD3D_Cube::getDepthStencil(GLenum target, GLint level) +RenderTarget *TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index) { - ASSERT(gl::IsCubemapTextureTarget(target)); + ASSERT(gl::IsCubemapTextureTarget(index.type)); // ensure the underlying texture is created if (!ensureRenderTarget()) @@ -1163,26 +1036,8 @@ RenderTarget *TextureD3D_Cube::getDepthStencil(GLenum target, GLint level) return NULL; } - updateStorageFaceLevel(targetToIndex(target), level); - - // ensure this is a depth texture - if (!isDepth(target, level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(target, level); -} - -int TextureD3D_Cube::targetToIndex(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; + updateStorageFaceLevel(index.layerIndex, index.mipIndex); + return mTexStorage->getRenderTarget(index); } void TextureD3D_Cube::initializeStorage(bool renderTarget) @@ -1208,7 +1063,7 @@ void TextureD3D_Cube::initializeStorage(bool renderTarget) updateStorage(); } -TextureStorageInterfaceCube *TextureD3D_Cube::createCompleteStorage(bool renderTarget) const +TextureStorage *TextureD3D_Cube::createCompleteStorage(bool renderTarget) const { GLsizei size = getBaseLevelWidth(); @@ -1217,10 +1072,10 @@ TextureStorageInterfaceCube *TextureD3D_Cube::createCompleteStorage(bool renderT // use existing storage level count, when previously specified by TexStorage*D GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1)); - return new TextureStorageInterfaceCube(mRenderer, getBaseLevelInternalFormat(), renderTarget, size, levels); + return mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels); } -void TextureD3D_Cube::setCompleteTexStorage(TextureStorageInterfaceCube *newCompleteTexStorage) +void TextureD3D_Cube::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) { SafeDelete(mTexStorage); mTexStorage = newCompleteTexStorage; @@ -1231,7 +1086,7 @@ void TextureD3D_Cube::setCompleteTexStorage(TextureStorageInterfaceCube *newComp { for (int level = 0; level < mTexStorage->getLevelCount(); level++) { - mImageArray[faceIndex][level]->setManagedSurface(mTexStorage, faceIndex, level); + mImageArray[faceIndex][level]->setManagedSurfaceCube(mTexStorage, faceIndex, level); } } } @@ -1264,9 +1119,9 @@ bool TextureD3D_Cube::ensureRenderTarget() ASSERT(mTexStorage); if (!mTexStorage->isRenderTarget()) { - TextureStorageInterfaceCube *newRenderTargetStorage = createCompleteStorage(true); + TextureStorage *newRenderTargetStorage = createCompleteStorage(true); - if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) + if (!mRenderer->copyToRenderTargetCube(newRenderTargetStorage, mTexStorage)) { delete newRenderTargetStorage; return gl::error(GL_OUT_OF_MEMORY, false); @@ -1279,7 +1134,7 @@ bool TextureD3D_Cube::ensureRenderTarget() return (mTexStorage && mTexStorage->isRenderTarget()); } -TextureStorageInterface *TextureD3D_Cube::getBaseLevelStorage() +TextureStorage *TextureD3D_Cube::getBaseLevelStorage() { return mTexStorage; } @@ -1291,40 +1146,11 @@ const ImageD3D *TextureD3D_Cube::getBaseLevelImage() const return mImageArray[0][0]; } -bool TextureD3D_Cube::isMipmapCubeComplete() 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 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); @@ -1414,15 +1240,14 @@ void TextureD3D_Cube::commitRect(int faceIndex, GLint level, GLint xoffset, GLin if (isValidFaceLevel(faceIndex, level)) { ImageD3D *image = mImageArray[faceIndex][level]; - if (image->copyToStorage(mTexStorage, faceIndex, level, xoffset, yoffset, width, height)) + if (image->copyToStorageCube(mTexStorage, faceIndex, level, xoffset, yoffset, width, height)) image->markClean(); } } TextureD3D_3D::TextureD3D_3D(Renderer *renderer) - : Texture3DImpl(), - TextureD3D(renderer), + : TextureD3D(renderer), mTexStorage(NULL) { for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) @@ -1433,48 +1258,36 @@ TextureD3D_3D::TextureD3D_3D(Renderer *renderer) TextureD3D_3D::~TextureD3D_3D() { - SafeDelete(mTexStorage); - + // 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]; } -} - -TextureD3D_3D *TextureD3D_3D::makeTextureD3D_3D(Texture3DImpl *texture) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureD3D_3D*, texture)); - return static_cast(texture); -} - -TextureStorageInterface *TextureD3D_3D::getNativeTexture() -{ - // ensure the underlying texture is created - initializeStorage(false); - TextureStorageInterface *storage = getBaseLevelStorage(); - if (storage) - { - updateStorage(); - } - - return storage; + SafeDelete(mTexStorage); } -Image *TextureD3D_3D::getImage(int level) const +Image *TextureD3D_3D::getImage(int level, int layer) const { ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(layer == 0); return mImageArray[level]; } -void TextureD3D_3D::setUsage(GLenum usage) +Image *TextureD3D_3D::getImage(const gl::ImageIndex &index) const { - mUsage = usage; + ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(!index.hasLayer()); + ASSERT(index.type == GL_TEXTURE_3D); + return mImageArray[index.mipIndex]; } -void TextureD3D_3D::resetDirty() +GLsizei TextureD3D_3D::getLayerCount(int level) const { - mDirtyImages = false; + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return 1; } GLsizei TextureD3D_3D::getWidth(GLint level) const @@ -1511,13 +1324,14 @@ GLenum TextureD3D_3D::getInternalFormat(GLint level) const bool TextureD3D_3D::isDepth(GLint level) const { - return gl::GetDepthBits(getInternalFormat(level)) > 0; + return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -void TextureD3D_3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +void 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) { - GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat - : gl::GetSizedInternalFormat(format, type); + ASSERT(target == GL_TEXTURE_3D); + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + redefineImage(level, sizedInternalFormat, width, height, depth); bool fastUnpacked = false; @@ -1526,7 +1340,8 @@ void TextureD3D_3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei if (isFastUnpackable(unpack, sizedInternalFormat)) { // Will try to create RT storage if it does not exist - RenderTarget *destRenderTarget = getRenderTarget(level); + gl::ImageIndex index = gl::ImageIndex::Make3D(level); + RenderTarget *destRenderTarget = getRenderTarget(index); gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget)) @@ -1544,22 +1359,28 @@ void TextureD3D_3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei } } -void TextureD3D_3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) +void TextureD3D_3D::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, 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); TextureD3D::setCompressedImage(imageSize, pixels, mImageArray[level]); } -void TextureD3D_3D::subImage(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) +void 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 = getRenderTarget(level); + RenderTarget *destRenderTarget = getRenderTarget(index); gl::Box destArea(xoffset, yoffset, zoffset, width, height, depth); if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget)) @@ -1571,22 +1392,31 @@ void TextureD3D_3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zo } } - if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels, mImageArray[level])) + if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels, index)) { commitRect(level, xoffset, yoffset, zoffset, width, height, depth); } } -void TextureD3D_3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) +void TextureD3D_3D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) { + ASSERT(target == GL_TEXTURE_3D); + if (TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels, mImageArray[level])) { commitRect(level, xoffset, yoffset, zoffset, width, height, depth); } } +void TextureD3D_3D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + UNIMPLEMENTED(); +} + void 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); + // 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) bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0); @@ -1610,15 +1440,17 @@ void TextureD3D_3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLin sourceRect.y = y; sourceRect.height = height; - mRenderer->copyImage(source, sourceRect, - gl::GetFormat(getBaseLevelInternalFormat()), - xoffset, yoffset, zoffset, mTexStorage, level); + mRenderer->copyImage3D(source, sourceRect, + gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format, + xoffset, yoffset, zoffset, mTexStorage, level); } } } -void TextureD3D_3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +void 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); @@ -1634,53 +1466,22 @@ void TextureD3D_3D::storage(GLsizei levels, GLenum internalformat, GLsizei width mImmutable = true; - setCompleteTexStorage(new TextureStorageInterface3D(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, depth, levels)); + bool renderTarget = IsRenderTargetUsage(mUsage); + TextureStorage *storage = mRenderer->createTextureStorage3D(internalformat, renderTarget, width, height, depth, levels); + setCompleteTexStorage(storage); } -bool TextureD3D_3D::isSamplerComplete(const gl::SamplerState &samplerState) const +void TextureD3D_3D::bindTexImage(egl::Surface *surface) { - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei depth = getBaseLevelDepth(); - - if (width <= 0 || height <= 0 || depth <= 0) - { - return false; - } - - // TODO(geofflang): use context's texture caps - if (!mRenderer->getRendererTextureCaps().get(getInternalFormat(0)).filterable) - { - if (samplerState.magFilter != GL_NEAREST || - (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) - { - return false; - } - } - - if (IsMipmapFiltered(samplerState) && !isMipmapComplete()) - { - return false; - } - - return true; + UNREACHABLE(); } -bool TextureD3D_3D::isMipmapComplete() const +void TextureD3D_3D::releaseTexImage() { - int levelCount = mipLevels(); - - for (int level = 0; level < levelCount; level++) - { - if (!isLevelComplete(level)) - { - return false; - } - } - - return true; + UNREACHABLE(); } + void TextureD3D_3D::generateMipmaps() { // Purge array levels 1 through q and reset them to represent the generated mipmap levels. @@ -1695,10 +1496,10 @@ void TextureD3D_3D::generateMipmaps() if (mTexStorage && mTexStorage->isRenderTarget()) { + mTexStorage->generateMipmaps(); + for (int level = 1; level < levelCount; level++) { - mTexStorage->generateMipmap(level); - mImageArray[level]->markClean(); } } @@ -1711,12 +1512,12 @@ void TextureD3D_3D::generateMipmaps() } } -unsigned int TextureD3D_3D::getRenderTargetSerial(GLint level, GLint layer) +unsigned int TextureD3D_3D::getRenderTargetSerial(const gl::ImageIndex &index) { - return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level, layer) : 0); + return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(index) : 0); } -RenderTarget *TextureD3D_3D::getRenderTarget(GLint level) +RenderTarget *TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index) { // ensure the underlying texture is created if (!ensureRenderTarget()) @@ -1724,53 +1525,16 @@ RenderTarget *TextureD3D_3D::getRenderTarget(GLint level) return NULL; } - updateStorageLevel(level); - - // ensure this is NOT a depth texture - if (isDepth(level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(level); -} - -RenderTarget *TextureD3D_3D::getRenderTarget(GLint level, GLint layer) -{ - // ensure the underlying texture is created - if (!ensureRenderTarget()) + if (index.hasLayer()) { - return NULL; - } - - updateStorage(); - - // ensure this is NOT a depth texture - if (isDepth(level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(level, layer); -} - -RenderTarget *TextureD3D_3D::getDepthStencil(GLint level, GLint layer) -{ - // ensure the underlying texture is created - if (!ensureRenderTarget()) - { - return NULL; + updateStorage(); } - - updateStorageLevel(level); - - // ensure this is a depth texture - if (!isDepth(level)) + else { - return NULL; + updateStorageLevel(index.mipIndex); } - return mTexStorage->getRenderTarget(level, layer); + return mTexStorage->getRenderTarget(index); } void TextureD3D_3D::initializeStorage(bool renderTarget) @@ -1796,21 +1560,22 @@ void TextureD3D_3D::initializeStorage(bool renderTarget) updateStorage(); } -TextureStorageInterface3D *TextureD3D_3D::createCompleteStorage(bool renderTarget) const +TextureStorage *TextureD3D_3D::createCompleteStorage(bool renderTarget) 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)); - return new TextureStorageInterface3D(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, depth, levels); + return mRenderer->createTextureStorage3D(internalFormat, renderTarget, width, height, depth, levels); } -void TextureD3D_3D::setCompleteTexStorage(TextureStorageInterface3D *newCompleteTexStorage) +void TextureD3D_3D::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) { SafeDelete(mTexStorage); mTexStorage = newCompleteTexStorage; @@ -1842,9 +1607,9 @@ bool TextureD3D_3D::ensureRenderTarget() ASSERT(mTexStorage); if (!mTexStorage->isRenderTarget()) { - TextureStorageInterface3D *newRenderTargetStorage = createCompleteStorage(true); + TextureStorage *newRenderTargetStorage = createCompleteStorage(true); - if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) + if (!mRenderer->copyToRenderTarget3D(newRenderTargetStorage, mTexStorage)) { delete newRenderTargetStorage; return gl::error(GL_OUT_OF_MEMORY, false); @@ -1857,7 +1622,7 @@ bool TextureD3D_3D::ensureRenderTarget() return (mTexStorage && mTexStorage->isRenderTarget()); } -TextureStorageInterface *TextureD3D_3D::getBaseLevelStorage() +TextureStorage *TextureD3D_3D::getBaseLevelStorage() { return mTexStorage; } @@ -1967,7 +1732,7 @@ void TextureD3D_3D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint if (isValidLevel(level)) { ImageD3D *image = mImageArray[level]; - if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, zoffset, width, height, depth)) + if (image->copyToStorage3D(mTexStorage, level, xoffset, yoffset, zoffset, width, height, depth)) { image->markClean(); } @@ -1976,8 +1741,7 @@ void TextureD3D_3D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint TextureD3D_2DArray::TextureD3D_2DArray(Renderer *renderer) - : Texture2DArrayImpl(), - TextureD3D(renderer), + : TextureD3D(renderer), mTexStorage(NULL) { for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level) @@ -1989,29 +1753,11 @@ TextureD3D_2DArray::TextureD3D_2DArray(Renderer *renderer) TextureD3D_2DArray::~TextureD3D_2DArray() { - SafeDelete(mTexStorage); - + // 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(); -} - -TextureD3D_2DArray *TextureD3D_2DArray::makeTextureD3D_2DArray(Texture2DArrayImpl *texture) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureD3D_2DArray*, texture)); - return static_cast(texture); -} - -TextureStorageInterface *TextureD3D_2DArray::getNativeTexture() -{ - // ensure the underlying texture is created - initializeStorage(false); - - TextureStorageInterface *storage = getBaseLevelStorage(); - if (storage) - { - updateStorage(); - } - - return storage; + SafeDelete(mTexStorage); } Image *TextureD3D_2DArray::getImage(int level, int layer) const @@ -2021,20 +1767,18 @@ Image *TextureD3D_2DArray::getImage(int level, int layer) const return mImageArray[level][layer]; } -GLsizei TextureD3D_2DArray::getLayerCount(int level) const -{ - ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); - return mLayerCounts[level]; -} - -void TextureD3D_2DArray::setUsage(GLenum usage) +Image *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const { - mUsage = usage; + 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]; } -void TextureD3D_2DArray::resetDirty() +GLsizei TextureD3D_2DArray::getLayerCount(int level) const { - mDirtyImages = false; + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return mLayerCounts[level]; } GLsizei TextureD3D_2DArray::getWidth(GLint level) const @@ -2059,16 +1803,19 @@ GLenum TextureD3D_2DArray::getInternalFormat(GLint level) const bool TextureD3D_2DArray::isDepth(GLint level) const { - return gl::GetDepthBits(getInternalFormat(level)) > 0; + return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0; } -void TextureD3D_2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +void 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) { - GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat - : gl::GetSizedInternalFormat(format, type); + ASSERT(target == GL_TEXTURE_2D_ARRAY); + + GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type); + redefineImage(level, sizedInternalFormat, width, height, depth); - GLsizei inputDepthPitch = gl::GetDepthPitch(sizedInternalFormat, type, width, height, unpack.alignment); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpack.alignment); for (int i = 0; i < depth; i++) { @@ -2077,12 +1824,15 @@ void TextureD3D_2DArray::setImage(GLint level, GLsizei width, GLsizei height, GL } } -void TextureD3D_2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels) +void TextureD3D_2DArray::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, 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); - GLsizei inputDepthPitch = gl::GetDepthPitch(format, GL_UNSIGNED_BYTE, width, height, 1); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1); for (int i = 0; i < depth; i++) { @@ -2091,26 +1841,32 @@ void TextureD3D_2DArray::setCompressedImage(GLint level, GLenum format, GLsizei } } -void TextureD3D_2DArray::subImage(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) +void 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) { - GLenum internalformat = getInternalFormat(level); - GLsizei inputDepthPitch = gl::GetDepthPitch(internalformat, type, width, height, unpack.alignment); + 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; - if (TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type, unpack, layerPixels, mImageArray[level][layer])) + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer); + if (TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type, unpack, layerPixels, index)) { commitRect(level, xoffset, yoffset, layer, width, height); } } } -void TextureD3D_2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) +void TextureD3D_2DArray::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) { - GLsizei inputDepthPitch = gl::GetDepthPitch(format, GL_UNSIGNED_BYTE, width, height, 1); + 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++) { @@ -2124,8 +1880,15 @@ void TextureD3D_2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yo } } +void TextureD3D_2DArray::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + UNIMPLEMENTED(); +} + void 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); + // 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) bool canCreateRenderTarget = isLevelComplete(level) && isLevelComplete(0); @@ -2149,14 +1912,16 @@ void TextureD3D_2DArray::copySubImage(GLenum target, GLint level, GLint xoffset, sourceRect.y = y; sourceRect.height = height; - mRenderer->copyImage(source, sourceRect, gl::GetFormat(getInternalFormat(0)), - xoffset, yoffset, zoffset, mTexStorage, level); + mRenderer->copyImage2DArray(source, sourceRect, gl::GetInternalFormatInfo(getInternalFormat(0)).format, + xoffset, yoffset, zoffset, mTexStorage, level); } } } -void TextureD3D_2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +void 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++) @@ -2181,53 +1946,23 @@ void TextureD3D_2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei } mImmutable = true; - setCompleteTexStorage(new TextureStorageInterface2DArray(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, depth, levels)); + + bool renderTarget = IsRenderTargetUsage(mUsage); + TextureStorage *storage = mRenderer->createTextureStorage2DArray(internalformat, renderTarget, width, height, depth, levels); + setCompleteTexStorage(storage); } -bool TextureD3D_2DArray::isSamplerComplete(const gl::SamplerState &samplerState) const +void TextureD3D_2DArray::bindTexImage(egl::Surface *surface) { - GLsizei width = getBaseLevelWidth(); - GLsizei height = getBaseLevelHeight(); - GLsizei depth = getLayers(0); - - if (width <= 0 || height <= 0 || depth <= 0) - { - return false; - } - - // TODO(geofflang): use context's texture caps - if (!mRenderer->getRendererTextureCaps().get(getBaseLevelInternalFormat()).filterable) - { - if (samplerState.magFilter != GL_NEAREST || - (samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) - { - return false; - } - } - - if (IsMipmapFiltered(samplerState) && !isMipmapComplete()) - { - return false; - } - - return true; + UNREACHABLE(); } -bool TextureD3D_2DArray::isMipmapComplete() const +void TextureD3D_2DArray::releaseTexImage() { - int levelCount = mipLevels(); - - for (int level = 1; level < levelCount; level++) - { - if (!isLevelComplete(level)) - { - return false; - } - } - - return true; + UNREACHABLE(); } + void TextureD3D_2DArray::generateMipmaps() { int baseWidth = getBaseLevelWidth(); @@ -2244,10 +1979,10 @@ void TextureD3D_2DArray::generateMipmaps() if (mTexStorage && mTexStorage->isRenderTarget()) { + mTexStorage->generateMipmaps(); + for (int level = 1; level < levelCount; level++) { - mTexStorage->generateMipmap(level); - for (int layer = 0; layer < mLayerCounts[level]; layer++) { mImageArray[level][layer]->markClean(); @@ -2266,31 +2001,12 @@ void TextureD3D_2DArray::generateMipmaps() } } -unsigned int TextureD3D_2DArray::getRenderTargetSerial(GLint level, GLint layer) +unsigned int TextureD3D_2DArray::getRenderTargetSerial(const gl::ImageIndex &index) { - return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level, layer) : 0); -} - -RenderTarget *TextureD3D_2DArray::getRenderTarget(GLint level, GLint layer) -{ - // ensure the underlying texture is created - if (!ensureRenderTarget()) - { - return NULL; - } - - updateStorageLevel(level); - - // ensure this is NOT a depth texture - if (isDepth(level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(level, layer); + return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(index) : 0); } -RenderTarget *TextureD3D_2DArray::getDepthStencil(GLint level, GLint layer) +RenderTarget *TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index) { // ensure the underlying texture is created if (!ensureRenderTarget()) @@ -2298,15 +2014,8 @@ RenderTarget *TextureD3D_2DArray::getDepthStencil(GLint level, GLint layer) return NULL; } - updateStorageLevel(level); - - // ensure this is a depth texture - if (!isDepth(level)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(level, layer); + updateStorageLevel(index.mipIndex); + return mTexStorage->getRenderTarget(index); } void TextureD3D_2DArray::initializeStorage(bool renderTarget) @@ -2332,21 +2041,22 @@ void TextureD3D_2DArray::initializeStorage(bool renderTarget) updateStorage(); } -TextureStorageInterface2DArray *TextureD3D_2DArray::createCompleteStorage(bool renderTarget) const +TextureStorage *TextureD3D_2DArray::createCompleteStorage(bool renderTarget) const { GLsizei width = getBaseLevelWidth(); GLsizei height = getBaseLevelHeight(); GLsizei depth = getLayers(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)); - return new TextureStorageInterface2DArray(mRenderer, getBaseLevelInternalFormat(), renderTarget, width, height, depth, levels); + return mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, width, height, depth, levels); } -void TextureD3D_2DArray::setCompleteTexStorage(TextureStorageInterface2DArray *newCompleteTexStorage) +void TextureD3D_2DArray::setCompleteTexStorage(TextureStorage *newCompleteTexStorage) { SafeDelete(mTexStorage); mTexStorage = newCompleteTexStorage; @@ -2378,9 +2088,9 @@ bool TextureD3D_2DArray::ensureRenderTarget() ASSERT(mTexStorage); if (!mTexStorage->isRenderTarget()) { - TextureStorageInterface2DArray *newRenderTargetStorage = createCompleteStorage(true); + TextureStorage *newRenderTargetStorage = createCompleteStorage(true); - if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) + if (!mRenderer->copyToRenderTarget2DArray(newRenderTargetStorage, mTexStorage)) { delete newRenderTargetStorage; return gl::error(GL_OUT_OF_MEMORY, false); @@ -2398,7 +2108,7 @@ const ImageD3D *TextureD3D_2DArray::getBaseLevelImage() const return (mLayerCounts[0] > 0 ? mImageArray[0][0] : NULL); } -TextureStorageInterface *TextureD3D_2DArray::getBaseLevelStorage() +TextureStorage *TextureD3D_2DArray::getBaseLevelStorage() { return mTexStorage; } @@ -2540,7 +2250,7 @@ void TextureD3D_2DArray::commitRect(GLint level, GLint xoffset, GLint yoffset, G if (isValidLevel(level) && layerTarget < getLayers(level)) { ImageD3D *image = mImageArray[level][layerTarget]; - if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, layerTarget, width, height)) + if (image->copyToStorage2DArray(mTexStorage, level, xoffset, yoffset, layerTarget, width, height)) { image->markClean(); } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h index 4a1737a9c4..41c73180de 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h @@ -24,20 +24,23 @@ namespace rx class Image; class ImageD3D; class Renderer; -class TextureStorageInterface; -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; -class TextureStorageInterface3D; -class TextureStorageInterface2DArray; +class RenderTarget; +class TextureStorage; -bool IsMipmapFiltered(const gl::SamplerState &samplerState); - -class TextureD3D +class TextureD3D : public TextureImpl { public: TextureD3D(Renderer *renderer); virtual ~TextureD3D(); + static TextureD3D *makeTextureD3D(TextureImpl *texture); + + virtual 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; @@ -45,16 +48,19 @@ class TextureD3D bool isImmutable() const { return mImmutable; } + virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index) = 0; + virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index) = 0; + protected: void setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, Image *image); bool subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, - GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, Image *image); + GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index); void setCompressedImage(GLsizei imageSize, const void *pixels, Image *image); bool subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels, Image *image); bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat); bool fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea, - GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget); + GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget); GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const; int mipLevels() const; @@ -70,25 +76,22 @@ class TextureD3D private: DISALLOW_COPY_AND_ASSIGN(TextureD3D); - virtual TextureStorageInterface *getBaseLevelStorage() = 0; + virtual void initializeStorage(bool renderTarget) = 0; + + virtual void updateStorage() = 0; + virtual TextureStorage *getBaseLevelStorage() = 0; virtual const ImageD3D *getBaseLevelImage() const = 0; }; -class TextureD3D_2D : public Texture2DImpl, public TextureD3D +class TextureD3D_2D : public TextureD3D { public: TextureD3D_2D(Renderer *renderer); virtual ~TextureD3D_2D(); - static TextureD3D_2D *makeTextureD3D_2D(Texture2DImpl *texture); - - virtual TextureStorageInterface *getNativeTexture(); - - virtual Image *getImage(int level) const; - - virtual void setUsage(GLenum usage); - virtual bool hasDirtyImages() const { return mDirtyImages; } - virtual void resetDirty(); + 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; @@ -96,104 +99,94 @@ class TextureD3D_2D : public Texture2DImpl, public TextureD3D GLenum getActualFormat(GLint level) const; bool isDepth(GLint level) const; - virtual void setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); - virtual void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); - virtual void copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + virtual void 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 void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); + virtual void 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 void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); + virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); + virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const; virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); virtual void generateMipmaps(); - virtual unsigned int getRenderTargetSerial(GLint level); - - virtual RenderTarget *getRenderTarget(GLint level); - virtual RenderTarget *getDepthSencil(GLint level); + virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); + virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); private: DISALLOW_COPY_AND_ASSIGN(TextureD3D_2D); - void initializeStorage(bool renderTarget); - TextureStorageInterface2D *createCompleteStorage(bool renderTarget) const; - void setCompleteTexStorage(TextureStorageInterface2D *newCompleteTexStorage); + virtual void initializeStorage(bool renderTarget); + TextureStorage *createCompleteStorage(bool renderTarget) const; + void setCompleteTexStorage(TextureStorage *newCompleteTexStorage); - void updateStorage(); + virtual void updateStorage(); bool ensureRenderTarget(); - virtual TextureStorageInterface *getBaseLevelStorage(); + virtual TextureStorage *getBaseLevelStorage(); virtual const ImageD3D *getBaseLevelImage() const; - bool isMipmapComplete() const; bool isValidLevel(int level) const; bool isLevelComplete(int level) const; void updateStorageLevel(int level); - virtual void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height); + void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height); void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - TextureStorageInterface2D *mTexStorage; + TextureStorage *mTexStorage; ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; }; -class TextureD3D_Cube : public TextureCubeImpl, public TextureD3D +class TextureD3D_Cube : public TextureD3D { public: TextureD3D_Cube(Renderer *renderer); virtual ~TextureD3D_Cube(); - static TextureD3D_Cube *makeTextureD3D_Cube(TextureCubeImpl *texture); - - virtual TextureStorageInterface *getNativeTexture(); - - virtual Image *getImage(GLenum target, int level) const; + virtual Image *getImage(int level, int layer) const; + virtual Image *getImage(const gl::ImageIndex &index) const; + virtual GLsizei getLayerCount(int level) const; - virtual void setUsage(GLenum usage); virtual bool hasDirtyImages() const { return mDirtyImages; } - virtual void resetDirty(); + virtual void resetDirty() { mDirtyImages = false; } + virtual void setUsage(GLenum usage) { mUsage = usage; } - GLenum getInternalFormat(GLenum target, GLint level) const; - bool isDepth(GLenum target, GLint level) const; + GLenum getInternalFormat(GLint level, GLint layer) const; + bool isDepth(GLint level, GLint layer) const; - virtual void setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); - virtual void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels); + virtual void 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 void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); + virtual void 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 void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual void storage(GLsizei levels, GLenum internalformat, GLsizei size); + virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const; - virtual bool isCubeComplete() const; + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); virtual void generateMipmaps(); - virtual unsigned int getRenderTargetSerial(GLenum target, GLint level); - - virtual RenderTarget *getRenderTarget(GLenum target, GLint level); - virtual RenderTarget *getDepthStencil(GLenum target, GLint level); - - static int targetToIndex(GLenum target); + virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); + virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); private: DISALLOW_COPY_AND_ASSIGN(TextureD3D_Cube); - void initializeStorage(bool renderTarget); - TextureStorageInterfaceCube *createCompleteStorage(bool renderTarget) const; - void setCompleteTexStorage(TextureStorageInterfaceCube *newCompleteTexStorage); + virtual void initializeStorage(bool renderTarget); + TextureStorage *createCompleteStorage(bool renderTarget) const; + void setCompleteTexStorage(TextureStorage *newCompleteTexStorage); - void updateStorage(); + virtual void updateStorage(); bool ensureRenderTarget(); - virtual TextureStorageInterface *getBaseLevelStorage(); + virtual TextureStorage *getBaseLevelStorage(); virtual const ImageD3D *getBaseLevelImage() const; - bool isMipmapCubeComplete() const; bool isValidFaceLevel(int faceIndex, int level) const; bool isFaceLevelComplete(int faceIndex, int level) const; + bool isCubeComplete() const; void updateStorageFaceLevel(int faceIndex, int level); void redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height); @@ -201,24 +194,18 @@ class TextureD3D_Cube : public TextureCubeImpl, public TextureD3D ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - TextureStorageInterfaceCube *mTexStorage; + TextureStorage *mTexStorage; }; -class TextureD3D_3D : public Texture3DImpl, public TextureD3D +class TextureD3D_3D : public TextureD3D { public: TextureD3D_3D(Renderer *renderer); virtual ~TextureD3D_3D(); - static TextureD3D_3D *makeTextureD3D_3D(Texture3DImpl *texture); - - virtual TextureStorageInterface *getNativeTexture(); - - virtual Image *getImage(int level) const; - - virtual void setUsage(GLenum usage); - virtual bool hasDirtyImages() const { return mDirtyImages; } - virtual void resetDirty(); + 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; @@ -226,34 +213,32 @@ class TextureD3D_3D : public Texture3DImpl, public TextureD3D GLenum getInternalFormat(GLint level) const; bool isDepth(GLint level) const; - virtual void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); - virtual void subImage(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 void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); + virtual void 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 void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); + virtual void 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 void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); + virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const; - virtual bool isMipmapComplete() const; + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); virtual void generateMipmaps(); - virtual unsigned int getRenderTargetSerial(GLint level, GLint layer); - - virtual RenderTarget *getRenderTarget(GLint level); - virtual RenderTarget *getRenderTarget(GLint level, GLint layer); - virtual RenderTarget *getDepthStencil(GLint level, GLint layer); + virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); + virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); private: DISALLOW_COPY_AND_ASSIGN(TextureD3D_3D); virtual void initializeStorage(bool renderTarget); - TextureStorageInterface3D *createCompleteStorage(bool renderTarget) const; - void setCompleteTexStorage(TextureStorageInterface3D *newCompleteTexStorage); + TextureStorage *createCompleteStorage(bool renderTarget) const; + void setCompleteTexStorage(TextureStorage *newCompleteTexStorage); - void updateStorage(); + virtual void updateStorage(); bool ensureRenderTarget(); - virtual TextureStorageInterface *getBaseLevelStorage(); + virtual TextureStorage *getBaseLevelStorage(); virtual const ImageD3D *getBaseLevelImage() const; bool isValidLevel(int level) const; @@ -265,59 +250,51 @@ class TextureD3D_3D : public Texture3DImpl, public TextureD3D ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - TextureStorageInterface3D *mTexStorage; + TextureStorage *mTexStorage; }; -class TextureD3D_2DArray : public Texture2DArrayImpl, public TextureD3D +class TextureD3D_2DArray : public TextureD3D { public: TextureD3D_2DArray(Renderer *renderer); virtual ~TextureD3D_2DArray(); - static TextureD3D_2DArray *makeTextureD3D_2DArray(Texture2DArrayImpl *texture); - - virtual TextureStorageInterface *getNativeTexture(); - virtual Image *getImage(int level, int layer) const; + virtual Image *getImage(const gl::ImageIndex &index) const; virtual GLsizei getLayerCount(int level) const; - virtual void setUsage(GLenum usage); - virtual bool hasDirtyImages() const { return mDirtyImages; } - virtual void resetDirty(); - GLsizei getWidth(GLint level) const; GLsizei getHeight(GLint level) const; GLsizei getLayers(GLint level) const; GLenum getInternalFormat(GLint level) const; bool isDepth(GLint level) const; - virtual void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels); - virtual void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); - virtual void subImage(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 void subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); + virtual void 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 void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); + virtual void 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 void subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels); + virtual void copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - virtual void storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + virtual void storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); - virtual bool isSamplerComplete(const gl::SamplerState &samplerState) const; - virtual bool isMipmapComplete() const; + virtual void bindTexImage(egl::Surface *surface); + virtual void releaseTexImage(); virtual void generateMipmaps(); - virtual unsigned int getRenderTargetSerial(GLint level, GLint layer); - - virtual RenderTarget *getRenderTarget(GLint level, GLint layer); - virtual RenderTarget *getDepthStencil(GLint level, GLint layer); + virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); + virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index); private: DISALLOW_COPY_AND_ASSIGN(TextureD3D_2DArray); virtual void initializeStorage(bool renderTarget); - TextureStorageInterface2DArray *createCompleteStorage(bool renderTarget) const; - void setCompleteTexStorage(TextureStorageInterface2DArray *newCompleteTexStorage); + TextureStorage *createCompleteStorage(bool renderTarget) const; + void setCompleteTexStorage(TextureStorage *newCompleteTexStorage); - void updateStorage(); + virtual void updateStorage(); bool ensureRenderTarget(); - virtual TextureStorageInterface *getBaseLevelStorage(); + virtual TextureStorage *getBaseLevelStorage(); virtual const ImageD3D *getBaseLevelImage() const; bool isValidLevel(int level) const; @@ -335,7 +312,7 @@ class TextureD3D_2DArray : public Texture2DArrayImpl, public TextureD3D GLsizei mLayerCounts[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; ImageD3D **mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - TextureStorageInterface2DArray *mTexStorage; + TextureStorage *mTexStorage; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp index 846586984c..dedd266c09 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp @@ -1,13 +1,10 @@ -#include "precompiled.h" // // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -// TextureStorage.cpp: Implements the abstract rx::TextureStorageInterface class and its concrete derived -// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the -// GPU-side texture. +// TextureStorage.cpp: Shared members of abstract rx::TextureStorage class. #include "libGLESv2/renderer/d3d/TextureStorage.h" #include "libGLESv2/renderer/d3d/TextureD3D.h" @@ -20,162 +17,35 @@ namespace rx { -unsigned int TextureStorageInterface::mCurrentTextureSerial = 1; -TextureStorageInterface::TextureStorageInterface() - : mTextureSerial(issueTextureSerial()), - mInstance(NULL) -{ -} +unsigned int TextureStorage::mCurrentTextureSerial = 1; -TextureStorageInterface::~TextureStorageInterface() -{ - delete mInstance; -} +TextureStorage::TextureStorage() + : mTextureSerial(issueTextureSerial()), + mFirstRenderTargetSerial(0), + mRenderTargetSerialsLayerStride(0) +{} -bool TextureStorageInterface::isRenderTarget() const +void TextureStorage::initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride) { - return mInstance->isRenderTarget(); + mFirstRenderTargetSerial = gl::RenderbufferStorage::issueSerials(rtSerialsToReserve); + mRenderTargetSerialsLayerStride = rtSerialsLayerStride; } -bool TextureStorageInterface::isManaged() const +unsigned int TextureStorage::getRenderTargetSerial(const gl::ImageIndex &index) const { - return mInstance->isManaged(); + unsigned int layerOffset = (index.hasLayer() ? (static_cast(index.layerIndex) * mRenderTargetSerialsLayerStride) : 0); + return mFirstRenderTargetSerial + static_cast(index.mipIndex) + layerOffset; } -unsigned int TextureStorageInterface::getTextureSerial() const +unsigned int TextureStorage::getTextureSerial() const { return mTextureSerial; } -unsigned int TextureStorageInterface::issueTextureSerial() +unsigned int TextureStorage::issueTextureSerial() { return mCurrentTextureSerial++; } -int TextureStorageInterface::getTopLevel() const -{ - return mInstance->getTopLevel(); -} - -int TextureStorageInterface::getLevelCount() const -{ - return mInstance->getLevelCount(); -} - -TextureStorageInterface2D::TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain) -{ - mFirstRenderTargetSerial = gl::RenderbufferStorage::issueSerials(1); - - mInstance = renderer->createTextureStorage2D(swapchain); -} - -TextureStorageInterface2D::TextureStorageInterface2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) -{ - mInstance = renderer->createTextureStorage2D(internalformat, renderTarget, width, height, levels); - mFirstRenderTargetSerial = gl::RenderbufferStorage::issueSerials(static_cast(mInstance->getLevelCount())); -} - -TextureStorageInterface2D::~TextureStorageInterface2D() -{ -} - -RenderTarget *TextureStorageInterface2D::getRenderTarget(GLint level) const -{ - return mInstance->getRenderTarget(level); -} - -void TextureStorageInterface2D::generateMipmap(int level) -{ - mInstance->generateMipmap(level); -} - -unsigned int TextureStorageInterface2D::getRenderTargetSerial(GLint level) const -{ - return mFirstRenderTargetSerial + level; -} - -TextureStorageInterfaceCube::TextureStorageInterfaceCube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels) -{ - mInstance = renderer->createTextureStorageCube(internalformat, renderTarget, size, levels); - mFirstRenderTargetSerial = gl::RenderbufferStorage::issueSerials(static_cast(mInstance->getLevelCount() * 6)); -} - -TextureStorageInterfaceCube::~TextureStorageInterfaceCube() -{ -} - -RenderTarget *TextureStorageInterfaceCube::getRenderTarget(GLenum faceTarget, GLint level) const -{ - return mInstance->getRenderTargetFace(faceTarget, level); -} - -void TextureStorageInterfaceCube::generateMipmap(int faceIndex, int level) -{ - mInstance->generateMipmap(faceIndex, level); -} - -unsigned int TextureStorageInterfaceCube::getRenderTargetSerial(GLenum target, GLint level) const -{ - return mFirstRenderTargetSerial + (level * 6) + TextureD3D_Cube::targetToIndex(target); -} - -TextureStorageInterface3D::TextureStorageInterface3D(Renderer *renderer, GLenum internalformat, bool renderTarget, - GLsizei width, GLsizei height, GLsizei depth, int levels) -{ - - mInstance = renderer->createTextureStorage3D(internalformat, renderTarget, width, height, depth, levels); - mFirstRenderTargetSerial = gl::RenderbufferStorage::issueSerials(static_cast(mInstance->getLevelCount() * depth)); -} - -TextureStorageInterface3D::~TextureStorageInterface3D() -{ -} - -void TextureStorageInterface3D::generateMipmap(int level) -{ - mInstance->generateMipmap(level); -} - -RenderTarget *TextureStorageInterface3D::getRenderTarget(GLint level) const -{ - return mInstance->getRenderTarget(level); -} - -RenderTarget *TextureStorageInterface3D::getRenderTarget(GLint level, GLint layer) const -{ - return mInstance->getRenderTargetLayer(level, layer); -} - -unsigned int TextureStorageInterface3D::getRenderTargetSerial(GLint level, GLint layer) const -{ - return mFirstRenderTargetSerial + static_cast((layer * mInstance->getLevelCount()) + level); -} - -TextureStorageInterface2DArray::TextureStorageInterface2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget, - GLsizei width, GLsizei height, GLsizei depth, int levels) -{ - mInstance = renderer->createTextureStorage2DArray(internalformat, renderTarget, width, height, depth, levels); - mFirstRenderTargetSerial = gl::RenderbufferStorage::issueSerials(static_cast(mInstance->getLevelCount() * depth)); -} - -TextureStorageInterface2DArray::~TextureStorageInterface2DArray() -{ -} - -void TextureStorageInterface2DArray::generateMipmap(int level) -{ - mInstance->generateMipmap(level); -} - -RenderTarget *TextureStorageInterface2DArray::getRenderTarget(GLint level, GLint layer) const -{ - return mInstance->getRenderTargetLayer(level, layer); -} - -unsigned int TextureStorageInterface2DArray::getRenderTargetSerial(GLint level, GLint layer) const -{ - return mFirstRenderTargetSerial + static_cast((layer * mInstance->getLevelCount()) + level); -} - } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h index 0a212e16f2..9cc2c2977b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h @@ -4,15 +4,20 @@ // found in the LICENSE file. // -// TextureStorage.h: Defines the abstract rx::TextureStorageInterface class and its concrete derived -// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the -// GPU-side texture. +// TextureStorage.h: Defines the abstract rx::TextureStorage class. #ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ #define LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ #include "common/debug.h" +#include + +namespace gl +{ +struct ImageIndex; +} + namespace rx { class Renderer; @@ -22,7 +27,7 @@ class RenderTarget; class TextureStorage { public: - TextureStorage() {}; + TextureStorage(); virtual ~TextureStorage() {}; virtual int getTopLevel() const = 0; @@ -30,114 +35,25 @@ class TextureStorage virtual bool isManaged() const = 0; virtual int getLevelCount() const = 0; - virtual RenderTarget *getRenderTarget(int level) = 0; - virtual RenderTarget *getRenderTargetFace(GLenum faceTarget, int level) = 0; - virtual RenderTarget *getRenderTargetLayer(int mipLevel, int layer) = 0; - virtual void generateMipmap(int level) = 0; - virtual void generateMipmap(int face, int level) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage); - -}; - -class TextureStorageInterface -{ - public: - TextureStorageInterface(); - virtual ~TextureStorageInterface(); - - TextureStorage *getStorageInstance() { return mInstance; } + virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index) = 0; + virtual void generateMipmaps() = 0; + unsigned int getRenderTargetSerial(const gl::ImageIndex &index) const; unsigned int getTextureSerial() const; - virtual int getTopLevel() const; - virtual bool isRenderTarget() const; - virtual bool isManaged() const; - virtual int getLevelCount() const; - protected: - TextureStorage *mInstance; + void initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride); private: - DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface); + DISALLOW_COPY_AND_ASSIGN(TextureStorage); const unsigned int mTextureSerial; static unsigned int issueTextureSerial(); static unsigned int mCurrentTextureSerial; -}; - -class TextureStorageInterface2D : public TextureStorageInterface -{ - public: - TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain); - TextureStorageInterface2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); - virtual ~TextureStorageInterface2D(); - - void generateMipmap(int level); - RenderTarget *getRenderTarget(GLint level) const; - - unsigned int getRenderTargetSerial(GLint level) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface2D); - - unsigned int mFirstRenderTargetSerial; -}; - -class TextureStorageInterfaceCube : public TextureStorageInterface -{ - public: - TextureStorageInterfaceCube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels); - virtual ~TextureStorageInterfaceCube(); - - void generateMipmap(int faceIndex, int level); - RenderTarget *getRenderTarget(GLenum faceTarget, GLint level) const; - - virtual unsigned int getRenderTargetSerial(GLenum target, GLint level) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorageInterfaceCube); - - unsigned int mFirstRenderTargetSerial; -}; - -class TextureStorageInterface3D : public TextureStorageInterface -{ - public: - TextureStorageInterface3D(Renderer *renderer, GLenum internalformat, bool renderTarget, - GLsizei width, GLsizei height, GLsizei depth, int levels); - virtual ~TextureStorageInterface3D(); - - void generateMipmap(int level); - RenderTarget *getRenderTarget(GLint level) const; - RenderTarget *getRenderTarget(GLint level, GLint layer) const; - - virtual unsigned int getRenderTargetSerial(GLint level, GLint layer) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface3D); - - unsigned int mFirstRenderTargetSerial; -}; - -class TextureStorageInterface2DArray : public TextureStorageInterface -{ - public: - TextureStorageInterface2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget, - GLsizei width, GLsizei height, GLsizei depth, int levels); - virtual ~TextureStorageInterface2DArray(); - - void generateMipmap(int level); - RenderTarget *getRenderTarget(GLint level, GLint layer) const; - - virtual unsigned int getRenderTargetSerial(GLint level, GLint layer) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface2DArray); unsigned int mFirstRenderTargetSerial; + unsigned int mRenderTargetSerialsLayerStride; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp new file mode 100644 index 0000000000..11596006d0 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/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 "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 new file mode 100644 index 0000000000..7c367aba1d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/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 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 index 901ca196a8..4f85eb94fa 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -9,9 +8,10 @@ // 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/Renderer.h" #include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/renderer/d3d/BufferD3D.h" + #include "common/mathutil.h" namespace rx @@ -62,7 +62,7 @@ unsigned int VertexBufferInterface::getBufferSize() const return mVertexBuffer->getBufferSize(); } -bool VertexBufferInterface::setBufferSize(unsigned int size) +gl::Error VertexBufferInterface::setBufferSize(unsigned int size) { if (mVertexBuffer->getBufferSize() == 0) { @@ -84,34 +84,39 @@ void VertexBufferInterface::setWritePosition(unsigned int writePosition) mWritePosition = writePosition; } -bool VertexBufferInterface::discard() +gl::Error VertexBufferInterface::discard() { return mVertexBuffer->discard(); } -bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset) +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; - if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired)) + error = mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired); + if (error.isError()) { - return false; + return error; } if (mWritePosition + spaceRequired < mWritePosition) { - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, new vertex buffer write position would overflow."); } - if (!reserveSpace(mReservedSpace)) + error = reserveSpace(mReservedSpace); + if (error.isError()) { - return false; + return error; } mReservedSpace = 0; - if (!mVertexBuffer->storeVertexAttributes(attrib, currentValue, start, count, instances, mWritePosition)) + error = mVertexBuffer->storeVertexAttributes(attrib, currentValue, start, count, instances, mWritePosition); + if (error.isError()) { - return false; + return error; } if (outStreamOffset) @@ -124,21 +129,25 @@ bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &att // Align to 16-byte boundary mWritePosition = rx::roundUp(mWritePosition, 16u); - return true; + return gl::Error(GL_NO_ERROR); } -bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) +gl::Error VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) { + gl::Error error(GL_NO_ERROR); + unsigned int requiredSpace; - if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &requiredSpace)) + error = mVertexBuffer->getSpaceRequired(attrib, count, instances, &requiredSpace); + if (error.isError()) { - return false; + return error; } // Protect against integer overflow if (mReservedSpace + requiredSpace < mReservedSpace) { - return false; + 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; @@ -146,7 +155,7 @@ bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib // Align to 16-byte boundary mReservedSpace = rx::roundUp(mReservedSpace, 16u); - return true; + return gl::Error(GL_NO_ERROR); } VertexBuffer* VertexBufferInterface::getVertexBuffer() const @@ -197,25 +206,29 @@ StreamingVertexBufferInterface::~StreamingVertexBufferInterface() { } -bool StreamingVertexBufferInterface::reserveSpace(unsigned int size) +gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size) { - bool result = true; unsigned int curBufferSize = getBufferSize(); if (size > curBufferSize) { - result = setBufferSize(std::max(size, 3 * curBufferSize / 2)); + gl::Error error = setBufferSize(std::max(size, 3 * curBufferSize / 2)); + if (error.isError()) + { + return error; + } setWritePosition(0); } else if (getWritePosition() + size > curBufferSize) { - if (!discard()) + gl::Error error = discard(); + if (error.isError()) { - return false; + return error; } setWritePosition(0); } - return result; + return gl::Error(GL_NO_ERROR); } StaticVertexBufferInterface::StaticVertexBufferInterface(rx::Renderer *renderer) : VertexBufferInterface(renderer, false) @@ -251,46 +264,44 @@ bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &att return false; } -bool StaticVertexBufferInterface::reserveSpace(unsigned int size) +gl::Error StaticVertexBufferInterface::reserveSpace(unsigned int size) { unsigned int curSize = getBufferSize(); if (curSize == 0) { - setBufferSize(size); - return true; + return setBufferSize(size); } else if (curSize >= size) { - return true; + return gl::Error(GL_NO_ERROR); } else { - UNREACHABLE(); // Static vertex buffers can't be resized - return false; + UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION, "Internal error, Static vertex buffers can't be resized."); } } -bool StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset) +gl::Error StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset) { unsigned int streamOffset; - if (VertexBufferInterface::storeVertexAttributes(attrib, currentValue, start, count, instances, &streamOffset)) + gl::Error error = VertexBufferInterface::storeVertexAttributes(attrib, currentValue, start, count, instances, &streamOffset); + if (error.isError()) { - 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); + return error; + } - if (outStreamOffset) - { - *outStreamOffset = streamOffset; - } + 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); - return true; - } - else + if (outStreamOffset) { - return false; + *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 index c5022d8c9c..fa747d9cb4 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h @@ -11,6 +11,12 @@ #define LIBGLESV2_RENDERER_VERTEXBUFFER_H_ #include "common/angleutils.h" +#include "libGLESv2/Error.h" + +#include + +#include +#include namespace gl { @@ -28,16 +34,16 @@ class VertexBuffer VertexBuffer(); virtual ~VertexBuffer(); - virtual bool initialize(unsigned int size, bool dynamicUsage) = 0; + virtual gl::Error initialize(unsigned int size, bool dynamicUsage) = 0; - virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int offset) = 0; - virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, - unsigned int *outSpaceRequired) const = 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 bool setBufferSize(unsigned int size) = 0; - virtual bool discard() = 0; + virtual gl::Error setBufferSize(unsigned int size) = 0; + virtual gl::Error discard() = 0; unsigned int getSerial() const; @@ -57,14 +63,14 @@ class VertexBufferInterface VertexBufferInterface(rx::Renderer *renderer, bool dynamic); virtual ~VertexBufferInterface(); - bool reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances); + gl::Error reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances); unsigned int getBufferSize() const; unsigned int getSerial() const; - virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset); + 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; @@ -72,14 +78,14 @@ class VertexBufferInterface VertexBuffer* getVertexBuffer() const; protected: - virtual bool reserveSpace(unsigned int size) = 0; + virtual gl::Error reserveSpace(unsigned int size) = 0; unsigned int getWritePosition() const; void setWritePosition(unsigned int writePosition); - bool discard(); + gl::Error discard(); - bool setBufferSize(unsigned int size); + gl::Error setBufferSize(unsigned int size); private: DISALLOW_COPY_AND_ASSIGN(VertexBufferInterface); @@ -100,7 +106,7 @@ class StreamingVertexBufferInterface : public VertexBufferInterface ~StreamingVertexBufferInterface(); protected: - bool reserveSpace(unsigned int size); + gl::Error reserveSpace(unsigned int size); }; class StaticVertexBufferInterface : public VertexBufferInterface @@ -109,13 +115,13 @@ class StaticVertexBufferInterface : public VertexBufferInterface explicit StaticVertexBufferInterface(rx::Renderer *renderer); ~StaticVertexBufferInterface(); - bool storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset); + 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: - bool reserveSpace(unsigned int size); + gl::Error reserveSpace(unsigned int size); private: struct VertexElement diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp index fc2b8ff0df..7034b78eab 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -10,12 +9,11 @@ #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/renderer/d3d/VertexBuffer.h" -#include "libGLESv2/renderer/Renderer.h" namespace { @@ -84,37 +82,22 @@ VertexDataManager::~VertexDataManager() } } -GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[], - gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances) +gl::Error VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[], + gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances) { if (!mStreamingBuffer) { - return GL_OUT_OF_MEMORY; + 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 = (programBinary->getSemanticIndex(attributeIndex) != -1); - } - // Invalidate static buffers that don't contain matching attributes - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - if (translated[i].active && attribs[i].enabled) + if (translated[attributeIndex].active && attribs[attributeIndex].enabled) { - gl::Buffer *buffer = attribs[i].buffer.get(); - - if (buffer) - { - BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation()); - StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer(); - - if (staticBuffer && staticBuffer->getBufferSize() > 0 && !staticBuffer->lookupAttribute(attribs[i], NULL) && - !staticBuffer->directStoragePossible(attribs[i], currentValues[i])) - { - bufferImpl->invalidateStaticData(); - } - } + invalidateMatchingStaticData(attribs[attributeIndex], currentValues[attributeIndex]); } } @@ -123,40 +106,10 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], { if (translated[i].active && attribs[i].enabled) { - gl::Buffer *buffer = attribs[i].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(attribs[i], currentValues[i])) + gl::Error error = reserveSpaceForAttrib(attribs[i], currentValues[i], count, instances); + if (error.isError()) { - if (staticBuffer) - { - if (staticBuffer->getBufferSize() == 0) - { - int totalCount = ElementsInBuffer(attribs[i], bufferImpl->getSize()); - if (!staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0)) - { - return GL_OUT_OF_MEMORY; - } - } - } - else - { - int totalCount = StreamingBufferElementCount(attribs[i], count, instances); - - // [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 (bufferImpl && ElementsInBuffer(attribs[i], bufferImpl->getSize()) < totalCount) - { - return GL_INVALID_OPERATION; - } - - if (!mStreamingBuffer->reserveVertexSpace(attribs[i], totalCount, instances)) - { - return GL_OUT_OF_MEMORY; - } - } + return error; } } } @@ -168,77 +121,12 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], { if (attribs[i].enabled) { - gl::Buffer *buffer = attribs[i].buffer.get(); - - if (!buffer && attribs[i].pointer == NULL) + gl::Error error = storeAttribute(attribs[i], currentValues[i], &translated[i], + start, count, instances); + if (error.isError()) { - // This is an application error that would normally result in a crash, but we catch it and return an error - ERR("An enabled vertex array has no buffer and no pointer."); - return GL_INVALID_OPERATION; + return error; } - - 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(attribs[i], currentValues[i]); - - unsigned int streamOffset = 0; - unsigned int outputElementSize = 0; - - if (directStorage) - { - outputElementSize = ComputeVertexAttributeStride(attribs[i]); - streamOffset = attribs[i].offset + outputElementSize * start; - } - else if (staticBuffer) - { - if (!staticBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize)) - { - return GL_OUT_OF_MEMORY; - } - - if (!staticBuffer->lookupAttribute(attribs[i], &streamOffset)) - { - // Convert the entire buffer - int totalCount = ElementsInBuffer(attribs[i], storage->getSize()); - int startIndex = attribs[i].offset / ComputeVertexAttributeStride(attribs[i]); - - if (!staticBuffer->storeVertexAttributes(attribs[i], currentValues[i], -startIndex, totalCount, - 0, &streamOffset)) - { - return GL_OUT_OF_MEMORY; - } - } - - unsigned int firstElementOffset = (attribs[i].offset / ComputeVertexAttributeStride(attribs[i])) * outputElementSize; - unsigned int startOffset = (instances == 0 || attribs[i].divisor == 0) ? start * outputElementSize : 0; - if (streamOffset + firstElementOffset + startOffset < streamOffset) - { - return GL_OUT_OF_MEMORY; - } - - streamOffset += firstElementOffset + startOffset; - } - else - { - int totalCount = StreamingBufferElementCount(attribs[i], count, instances); - if (!mStreamingBuffer->getVertexBuffer()->getSpaceRequired(attribs[i], 1, 0, &outputElementSize) || - !mStreamingBuffer->storeVertexAttributes(attribs[i], currentValues[i], start, totalCount, instances, - &streamOffset)) - { - return GL_OUT_OF_MEMORY; - } - } - - translated[i].storage = directStorage ? storage : NULL; - translated[i].vertexBuffer = vertexBuffer->getVertexBuffer(); - translated[i].serial = directStorage ? storage->getSerial() : vertexBuffer->getSerial(); - translated[i].divisor = attribs[i].divisor; - - translated[i].attribute = &attribs[i]; - translated[i].currentValueType = currentValues[i].Type; - translated[i].stride = outputElementSize; - translated[i].offset = streamOffset; } else { @@ -247,34 +135,13 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE); } - StreamingVertexBufferInterface *buffer = mCurrentValueBuffer[i]; - - if (mCurrentValue[i] != currentValues[i]) + gl::Error error = storeCurrentValue(attribs[i], currentValues[i], &translated[i], + &mCurrentValue[i], &mCurrentValueOffsets[i], + mCurrentValueBuffer[i]); + if (error.isError()) { - if (!buffer->reserveVertexSpace(attribs[i], 1, 0)) - { - return GL_OUT_OF_MEMORY; - } - - unsigned int streamOffset; - if (!buffer->storeVertexAttributes(attribs[i], currentValues[i], 0, 1, 0, &streamOffset)) - { - return GL_OUT_OF_MEMORY; - } - - mCurrentValue[i] = currentValues[i]; - mCurrentValueOffsets[i] = streamOffset; + return error; } - - translated[i].storage = NULL; - translated[i].vertexBuffer = mCurrentValueBuffer[i]->getVertexBuffer(); - translated[i].serial = mCurrentValueBuffer[i]->getSerial(); - translated[i].divisor = 0; - - translated[i].attribute = &attribs[i]; - translated[i].currentValueType = currentValues[i].Type; - translated[i].stride = 0; - translated[i].offset = mCurrentValueOffsets[i]; } } } @@ -293,7 +160,189 @@ GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], } } - return GL_NO_ERROR; + 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 index 4164fbecbb..7728722246 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h @@ -30,6 +30,9 @@ class Renderer; 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; @@ -49,12 +52,34 @@ class VertexDataManager VertexDataManager(rx::Renderer *renderer); virtual ~VertexDataManager(); - GLenum prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[], - gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances); + gl::Error prepareVertexData(const gl::VertexAttribute attribs[], const gl::VertexAttribCurrentValueData currentValues[], + gl::ProgramBinary *programBinary, 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); + rx::Renderer *const mRenderer; StreamingVertexBufferInterface *mStreamingBuffer; 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 9b0f336ac7..d43e65ea78 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -7,12 +6,12 @@ // Blit11.cpp: Texture copy utility class. -#include "libGLESv2/main.h" -#include "libGLESv2/formatutils.h" #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" @@ -315,7 +314,6 @@ Blit11::Blit11(rx::Renderer11 *renderer) 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(); @@ -373,18 +371,20 @@ static inline unsigned int GetSwizzleIndex(GLenum swizzle) return colorIndex; } -bool Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size, - GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) +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); - GLenum sourceInternalFormat = d3d11_gl::GetInternalFormat(sourceSRVDesc.Format); + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format); + const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); GLenum shaderType = GL_NONE; - switch (gl::GetComponentType(sourceInternalFormat)) + switch (sourceFormatInfo.componentType) { case GL_UNSIGNED_NORMALIZED: case GL_SIGNED_NORMALIZED: @@ -410,7 +410,7 @@ bool Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTarget if (i == mSwizzleShaderMap.end()) { UNREACHABLE(); - return false; + return gl::Error(GL_INVALID_OPERATION, "Internal error, missing swizzle shader."); } const Shader &shader = i->second; @@ -420,8 +420,7 @@ bool Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTarget result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { - ERR("Failed to map vertex buffer for texture swizzle, HRESULT: 0x%X.", result); - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer for swizzle, HRESULT: 0x%X.", result); } UINT stride = 0; @@ -438,8 +437,7 @@ bool Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTarget result = deviceContext->Map(mSwizzleCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { - ERR("Failed to map constant buffer for texture swizzle, HRESULT: 0x%X.", result); - return false; + 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); @@ -506,7 +504,7 @@ bool Blit11::swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTarget mRenderer->markAllStateDirty(); - return true; + return gl::Error(GL_NO_ERROR); } bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, @@ -520,11 +518,13 @@ bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &source // 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); - GLenum sourceInternalFormat = d3d11_gl::GetInternalFormat(sourceSRVDesc.Format); + + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(sourceSRVDesc.Format); + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(dxgiFormatInfo.internalFormat); BlitParameters parameters = { 0 }; parameters.mDestinationFormat = destFormat; - parameters.mSignedInteger = gl::GetComponentType(sourceInternalFormat) == GL_INT; + parameters.mSignedInteger = (internalFormatInfo.componentType == GL_INT); parameters.m3DBlit = sourceArea.depth > 1; BlitShaderMap::const_iterator i = mBlitShaderMap.find(parameters); @@ -770,18 +770,19 @@ bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubreso DXGI_FORMAT format = GetTextureFormat(source); ASSERT(format == GetTextureFormat(dest)); - unsigned int pixelSize = d3d11::GetFormatPixelBytes(format); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(format); + unsigned int pixelSize = dxgiFormatInfo.pixelBytes; unsigned int copyOffset = 0; unsigned int copySize = pixelSize; if (stencilOnly) { - copyOffset = d3d11::GetStencilOffset(format) / 8; - copySize = d3d11::GetStencilBits(format) / 8; + 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(d3d11::GetStencilBits(format) % 8 == 0 && - d3d11::GetStencilOffset(format) % 8 == 0); + ASSERT(dxgiFormatInfo.stencilBits % 8 == 0 && + dxgiFormatInfo.depthBits % 8 == 0); } D3D11_MAPPED_SUBRESOURCE sourceMapping, destMapping; @@ -995,18 +996,17 @@ void Blit11::buildShaderMap() 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_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG 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_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R 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" )); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h index fba89e20ba..d6a0b795f4 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h @@ -11,6 +11,9 @@ #include "common/angleutils.h" #include "libGLESv2/angletypes.h" +#include "libGLESv2/Error.h" + +#include namespace rx { @@ -28,8 +31,8 @@ class Blit11 explicit Blit11(Renderer11 *renderer); ~Blit11(); - bool swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size, - GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); + gl::Error swizzleTexture(ID3D11ShaderResourceView *source, ID3D11RenderTargetView *dest, const gl::Extents &size, + GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); bool copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, 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 1301124b2d..ecd4d4672b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright 2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -8,13 +7,9 @@ // Buffer11.cpp Defines the Buffer11 class. #include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" -#include "libGLESv2/main.h" #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" - -#if defined(__MINGW32__) && !defined(D3D11_MAP_FLAG_DO_NOT_WAIT) -# define D3D11_MAP_FLAG_DO_NOT_WAIT 0x100000L -#endif +#include "libGLESv2/main.h" namespace rx { @@ -122,6 +117,8 @@ class Buffer11::NativeBuffer11 : public Buffer11::BufferStorage11 virtual void *map(size_t offset, size_t length, GLbitfield access); virtual void unmap(); + bool setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset); + private: ID3D11Buffer *mNativeBuffer; @@ -143,7 +140,7 @@ class Buffer11::PackStorage11 : public Buffer11::BufferStorage11 virtual void *map(size_t offset, size_t length, GLbitfield access); virtual void unmap(); - void packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); + gl::Error packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); private: @@ -166,12 +163,14 @@ Buffer11::Buffer11(Renderer11 *renderer) mMappedStorage(NULL), mResolvedDataRevision(0), mReadUsageCount(0) -{ -} +{} Buffer11::~Buffer11() { - clear(); + for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) + { + SafeDelete(it->second); + } } Buffer11 *Buffer11::makeBuffer11(BufferImpl *buffer) @@ -180,29 +179,20 @@ Buffer11 *Buffer11::makeBuffer11(BufferImpl *buffer) return static_cast(buffer); } -void Buffer11::clear() +gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage) { - for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) + gl::Error error = setSubData(data, size, 0); + if (error.isError()) { - SafeDelete(it->second); + return error; } - mBufferStorages.clear(); - - mSize = 0; - mResolvedDataRevision = 0; -} - -void Buffer11::setData(const void* data, size_t size, GLenum usage) -{ - mIndexRangeCache.clear(); - - setSubData(data, size, 0); - if (usage == GL_STATIC_DRAW) { initializeStaticData(); } + + return error; } void *Buffer11::getData() @@ -243,16 +233,23 @@ void *Buffer11::getData() 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, (void*)NULL); + } + } + + ASSERT(mResolvedData.size() >= mSize); + return mResolvedData.data(); } -void Buffer11::setSubData(const void* data, size_t size, size_t offset) +gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset) { size_t requiredSize = size + offset; - mSize = std::max(mSize, requiredSize); - - mIndexRangeCache.invalidateRange(offset, size); - invalidateStaticData(); if (data && size > 0) { @@ -260,8 +257,7 @@ void Buffer11::setSubData(const void* data, size_t size, size_t offset) if (!stagingBuffer) { - // Out-of-memory - return; + 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 @@ -271,65 +267,78 @@ void Buffer11::setSubData(const void* data, size_t size, size_t offset) bool preserveData = (offset > 0); if (!stagingBuffer->resize(requiredSize, preserveData)) { - // Out-of-memory - return; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal staging buffer."); } } - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_WRITE, 0, &mappedResource); - if (FAILED(result)) + if (!stagingBuffer->setData(D3D11_MAP_WRITE, reinterpret_cast(data), size, offset)) { - return gl::error(GL_OUT_OF_MEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to set data on internal staging buffer."); } - unsigned char *offsetBufferPointer = reinterpret_cast(mappedResource.pData) + offset; - memcpy(offsetBufferPointer, data, size); - - context->Unmap(stagingBuffer->getNativeBuffer(), 0); - stagingBuffer->setDataRevision(stagingBuffer->getDataRevision() + 1); } + + mSize = std::max(mSize, requiredSize); + invalidateStaticData(); + + return gl::Error(GL_NO_ERROR); } -void Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +gl::Error Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) { Buffer11 *sourceBuffer = makeBuffer11(source); - if (sourceBuffer) + 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()) { - BufferStorage11 *dest = getLatestBufferStorage(); - if (!dest) + 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) { - dest = getStagingBuffer(); + copySource = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); } - - BufferStorage11 *source = sourceBuffer->getLatestBufferStorage(); - if (source && dest) + else { - // 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 (dest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !source->isMappable()) - { - source = sourceBuffer->getStagingBuffer(); - } - else if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK && !dest->isMappable()) - { - dest = getStagingBuffer(); - } - - dest->copyFromStorage(source, sourceOffset, size, destOffset); - dest->setDataRevision(dest->getDataRevision() + 1); + copySource = getStagingBuffer(); } - - mSize = std::max(mSize, destOffset + size); } + copyDest->copyFromStorage(copySource, sourceOffset, size, destOffset); + copyDest->setDataRevision(copyDest->getDataRevision() + 1); + + mSize = std::max(mSize, destOffset + size); invalidateStaticData(); + + return gl::Error(GL_NO_ERROR); } -GLvoid *Buffer11::map(size_t offset, size_t length, GLbitfield access) +gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) { ASSERT(!mMappedStorage); @@ -350,8 +359,7 @@ GLvoid *Buffer11::map(size_t offset, size_t length, GLbitfield access) if (!mMappedStorage) { - // Out-of-memory - return NULL; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate mappable internal buffer."); } if ((access & GL_MAP_WRITE_BIT) > 0) @@ -360,14 +368,22 @@ GLvoid *Buffer11::map(size_t offset, size_t length, GLbitfield access) mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1); } - return mMappedStorage->map(offset, length, access); + 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); } -void Buffer11::unmap() +gl::Error Buffer11::unmap() { ASSERT(mMappedStorage); mMappedStorage->unmap(); mMappedStorage = NULL; + return gl::Error(GL_NO_ERROR); } void Buffer11::markTransformFeedbackUsage() @@ -448,9 +464,11 @@ ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) 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 / d3d11::GetFormatPixelBytes(srvFormat); + bufferSRVDesc.Buffer.ElementWidth = mSize / dxgiFormatInfo.pixelBytes; bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; bufferSRVDesc.Format = srvFormat; @@ -463,7 +481,7 @@ ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) return bufferSRV; } -void Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams ¶ms) +gl::Error Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams ¶ms) { PackStorage11 *packStorage = getPackStorage(); @@ -471,9 +489,15 @@ void Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, cons if (packStorage) { - packStorage->packPixels(srcTexture, srcSubresource, params); + 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) @@ -584,6 +608,14 @@ Buffer11::PackStorage11 *Buffer11::getPackStorage() 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), @@ -605,7 +637,7 @@ Buffer11::NativeBuffer11::~NativeBuffer11() // Returns true if it recreates the direct buffer bool Buffer11::NativeBuffer11::copyFromStorage(BufferStorage11 *source, size_t sourceOffset, - size_t size, size_t destOffset) + size_t size, size_t destOffset) { ID3D11DeviceContext *context = mRenderer->getDeviceContext(); @@ -716,7 +748,7 @@ 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; - if (renderer->getMaxTransformFeedbackBuffers() > 0) + if (!static_cast(renderer)->isLevel9()) bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT; bufferDesc->CPUAccessFlags = 0; break; @@ -741,7 +773,7 @@ void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Ren // 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->getMaxUniformBufferSize()); + bufferDesc->ByteWidth = std::min(bufferDesc->ByteWidth, renderer->getRendererCaps().maxUniformBlockSize); break; default: @@ -765,6 +797,25 @@ void *Buffer11::NativeBuffer11::map(size_t offset, size_t length, GLbitfield acc return static_cast(mappedResource.pData) + offset; } +bool 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, false); + } + + uint8_t *offsetBufferPointer = reinterpret_cast(mappedResource.pData) + offset; + memcpy(offsetBufferPointer, data, size); + + context->Unmap(mNativeBuffer, 0); + + return true; +} + void Buffer11::NativeBuffer11::unmap() { ASSERT(mUsage == BUFFER_USAGE_STAGING); @@ -788,9 +839,11 @@ Buffer11::PackStorage11::~PackStorage11() } bool Buffer11::PackStorage11::copyFromStorage(BufferStorage11 *source, size_t sourceOffset, - size_t size, size_t destOffset) + size_t size, size_t destOffset) { - UNIMPLEMENTED(); + // 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; } @@ -827,7 +880,7 @@ void Buffer11::PackStorage11::unmap() // No-op } -void Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms) +gl::Error Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms) { flushQueuedPackCommand(); mQueuedPackCommand = new PackPixelsParams(params); @@ -869,13 +922,15 @@ void Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSub stagingDesc.MiscFlags = 0; hr = device->CreateTexture2D(&stagingDesc, NULL, &mStagingTexture); - ASSERT(SUCCEEDED(hr)); + if (FAILED(hr)) + { + ASSERT(hr == E_OUTOFMEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging texture."); + } } - if (textureDesc.SampleDesc.Count > 1) - { - UNIMPLEMENTED(); - } + // ReadPixels from multisampled FBOs isn't supported in current GL + ASSERT(textureDesc.SampleDesc.Count <= 1); ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); D3D11_BOX srcBox; @@ -888,6 +943,8 @@ void Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSub // Asynchronous copy immediateContext->CopySubresourceRegion(mStagingTexture, 0, 0, 0, 0, srcTexure, srcSubresource, &srcBox); + + return gl::Error(GL_NO_ERROR); } void Buffer11::PackStorage11::flushQueuedPackCommand() diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h index e56be247c4..5f24fb4e2d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h @@ -55,21 +55,20 @@ class Buffer11 : public BufferD3D ID3D11Buffer *getBuffer(BufferUsage usage); ID3D11ShaderResourceView *getSRV(DXGI_FORMAT srvFormat); bool isMapped() const { return mMappedStorage != NULL; } - void packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); + gl::Error packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); // BufferD3D implementation virtual size_t getSize() const { return mSize; } - virtual void clear(); - virtual bool supportsDirectBinding() const { return true; } + virtual bool supportsDirectBinding() const; virtual Renderer* getRenderer(); // BufferImpl implementation - virtual void setData(const void* data, size_t size, GLenum usage); + virtual gl::Error setData(const void* data, size_t size, GLenum usage); virtual void *getData(); - virtual void setSubData(const void* data, size_t size, size_t offset); - virtual void copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); - virtual GLvoid* map(size_t offset, size_t length, GLbitfield access); - virtual void unmap(); + 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: 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 5121950da0..765d34fd3f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -11,11 +10,11 @@ #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" @@ -155,7 +154,7 @@ Clear11::~Clear11() SafeRelease(mRasterizerState); } -void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) +gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) { // First determine if a scissored clear is needed, this will always require drawing a quad. // @@ -190,7 +189,7 @@ void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Frame else { UNREACHABLE(); - return; + return gl::Error(GL_INVALID_OPERATION); } if (clearParams.scissorEnabled && (clearParams.scissor.x >= framebufferSize.width || @@ -199,7 +198,7 @@ void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Frame clearParams.scissor.y + clearParams.scissor.height <= 0)) { // Scissor is enabled and the scissor rectangle is outside the renderbuffer - return; + return gl::Error(GL_NO_ERROR); } bool needScissoredClear = clearParams.scissorEnabled && (clearParams.scissor.x > 0 || clearParams.scissor.y > 0 || @@ -218,41 +217,35 @@ void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Frame gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(colorAttachment); if (attachment) { - RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(attachment->getRenderTarget()); + RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(attachment); if (!renderTarget) { - ERR("Render target pointer unexpectedly null."); - return; + return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); } - GLenum internalFormat = attachment->getInternalFormat(); - GLenum actualFormat = attachment->getActualFormat(); - GLenum componentType = gl::GetComponentType(internalFormat); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat()); + if (clearParams.colorClearType == GL_FLOAT && - !(componentType == GL_FLOAT || componentType == GL_UNSIGNED_NORMALIZED || componentType == GL_SIGNED_NORMALIZED)) + !(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, internalFormat); + "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment, + attachment->getInternalFormat()); } - GLuint internalRedBits = gl::GetRedBits(internalFormat); - GLuint internalGreenBits = gl::GetGreenBits(internalFormat); - GLuint internalBlueBits = gl::GetBlueBits(internalFormat); - GLuint internalAlphaBits = gl::GetAlphaBits(internalFormat); - - if ((internalRedBits == 0 || !clearParams.colorMaskRed) && - (internalGreenBits == 0 || !clearParams.colorMaskGreen) && - (internalBlueBits == 0 || !clearParams.colorMaskBlue) && - (internalAlphaBits == 0 || !clearParams.colorMaskAlpha)) + 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 || - (internalRedBits > 0 && !clearParams.colorMaskRed) || - (internalGreenBits > 0 && !clearParams.colorMaskGreen) || - (internalBlueBits > 0 && !clearParams.colorMaskBlue) || - (internalAlphaBits > 0 && !clearParams.colorMaskAlpha)) + (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; @@ -271,23 +264,19 @@ void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Frame ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); if (!framebufferRTV) { - ERR("Render target view pointer unexpectedly null."); - return; + 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 - GLuint actualRedBits = gl::GetRedBits(actualFormat); - GLuint actualGreenBits = gl::GetGreenBits(actualFormat); - GLuint actualBlueBits = gl::GetBlueBits(actualFormat); - GLuint actualAlphaBits = gl::GetAlphaBits(actualFormat); - const float clearValues[4] = { - ((internalRedBits == 0 && actualRedBits > 0) ? 0.0f : clearParams.colorFClearValue.red), - ((internalGreenBits == 0 && actualGreenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), - ((internalBlueBits == 0 && actualBlueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue), - ((internalAlphaBits == 0 && actualAlphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), + ((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); @@ -301,16 +290,15 @@ void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Frame gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer(); if (attachment) { - RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(attachment->getDepthStencil()); + RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(attachment); if (!renderTarget) { - ERR("Depth stencil render target pointer unexpectedly null."); - return; + return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null."); } - GLenum actualFormat = attachment->getActualFormat(); + const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat()); - unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << gl::GetStencilBits(actualFormat)) - 1 : 0; + unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << actualFormatInfo.stencilBits) - 1 : 0; bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; if (needScissoredClear || needMaskedStencilClear) @@ -322,8 +310,7 @@ void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Frame ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); if (!framebufferDSV) { - ERR("Depth stencil view pointer unexpectedly null."); - return; + return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null."); } UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | @@ -370,8 +357,7 @@ void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Frame ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView(); if (!rtv) { - ERR("Render target view unexpectedly null."); - return; + return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); } rtvs[i] = rtv; @@ -393,8 +379,7 @@ void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Frame HRESULT result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); if (FAILED(result)) { - ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result); - return; + 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; @@ -459,6 +444,8 @@ void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Frame // Clean up mRenderer->markAllStateDirty(); } + + return gl::Error(GL_NO_ERROR); } ID3D11BlendState *Clear11::getBlendState(const std::vector& rts) @@ -469,12 +456,12 @@ ID3D11BlendState *Clear11::getBlendState(const std::vector& if (i < rts.size()) { RenderTarget11 *rt = rts[i].renderTarget; - GLint internalFormat = rt->getInternalFormat(); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(rt->getInternalFormat()); - blendKey.maskChannels[i][0] = (rts[i].colorMask[0] && gl::GetRedBits(internalFormat) > 0); - blendKey.maskChannels[i][1] = (rts[i].colorMask[1] && gl::GetGreenBits(internalFormat) > 0); - blendKey.maskChannels[i][2] = (rts[i].colorMask[2] && gl::GetBlueBits(internalFormat) > 0); - blendKey.maskChannels[i][3] = (rts[i].colorMask[3] && gl::GetAlphaBits(internalFormat) > 0); + 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 { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h index 0cb9a85a6d..be8e187c40 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h @@ -10,6 +10,10 @@ #define LIBGLESV2_RENDERER_CLEAR11_H_ #include "libGLESv2/angletypes.h" +#include "libGLESv2/Error.h" + +#include +#include namespace gl { @@ -28,7 +32,7 @@ class Clear11 ~Clear11(); // Clears the framebuffer with the supplied clear parameters, assumes that the framebuffer is currently applied. - void clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); + gl::Error clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); private: Renderer11 *mRenderer; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp index 8698776650..a841b52862 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -8,8 +7,8 @@ // Fence11.cpp: Defines the rx::Fence11 class which implements rx::FenceImpl. #include "libGLESv2/renderer/d3d/d3d11/Fence11.h" -#include "libGLESv2/main.h" #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/main.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp index 2165bec305..7536713af4 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -11,13 +10,13 @@ #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" #include "libGLESv2/renderer/d3d/d3d11/Image11.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" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" -#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" namespace rx { @@ -27,11 +26,17 @@ Image11::Image11() mStagingTexture = NULL; mRenderer = NULL; mDXGIFormat = DXGI_FORMAT_UNKNOWN; + mRecoverFromStorage = false; + mAssociatedStorage = NULL; + mAssociatedStorageLevel = 0; + mAssociatedStorageLayerTarget = 0; + mRecoveredFromStorageCount = 0; } Image11::~Image11() { - SafeRelease(mStagingTexture); + disassociateStorage(); + releaseStagingTexture(); } Image11 *Image11::makeImage11(Image *img) @@ -46,8 +51,8 @@ void Image11::generateMipmap(Image11 *dest, Image11 *src) ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth()); ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight()); - MipGenerationFunction mipFunction = d3d11::GetMipGenerationFunction(src->getDXGIFormat()); - ASSERT(mipFunction != NULL); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(src->getDXGIFormat()); + ASSERT(dxgiFormatInfo.mipGenerationFunction != NULL); D3D11_MAPPED_SUBRESOURCE destMapped; HRESULT destMapResult = dest->map(D3D11_MAP_WRITE, &destMapped); @@ -70,8 +75,9 @@ void Image11::generateMipmap(Image11 *dest, Image11 *src) const uint8_t *sourceData = reinterpret_cast(srcMapped.pData); uint8_t *destData = reinterpret_cast(destMapped.pData); - mipFunction(src->getWidth(), src->getHeight(), src->getDepth(), sourceData, srcMapped.RowPitch, srcMapped.DepthPitch, - destData, destMapped.RowPitch, destMapped.DepthPitch); + dxgiFormatInfo.mipGenerationFunction(src->getWidth(), src->getHeight(), src->getDepth(), + sourceData, srcMapped.RowPitch, srcMapped.DepthPitch, + destData, destMapped.RowPitch, destMapped.DepthPitch); dest->unmap(); src->unmap(); @@ -81,33 +87,117 @@ void Image11::generateMipmap(Image11 *dest, Image11 *src) bool Image11::isDirty() const { - // Make sure that this image is marked as dirty even if the staging texture hasn't been created yet - // if initialization is required before use. - return (mDirty && (mStagingTexture || gl_d3d11::RequiresTextureDataInitialization(mInternalFormat))); + // 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; +} + +bool Image11::copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage); + return copyToStorageImpl(storage11, level, 0, xoffset, yoffset, width, height); } -bool Image11::copyToStorage(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +bool Image11::copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) { - TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); - return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, 0, width, height, 1); + TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage); + return copyToStorageImpl(storage11, level, face, xoffset, yoffset, width, height); } -bool Image11::copyToStorage(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +bool Image11::copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) { - TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); - return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, face, xoffset, yoffset, 0, width, height, 1); + TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage); + return copyToStorageImpl(storage11, level, 0, xoffset, yoffset, width, height); } -bool Image11::copyToStorage(TextureStorageInterface3D *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) +bool Image11::copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height) { - TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage->getStorageInstance()); - return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, zoffset, width, height, depth); + TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage); + return copyToStorageImpl(storage11, level, arrayLayer, xoffset, yoffset, width, height); } -bool Image11::copyToStorage(TextureStorageInterface2DArray *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height) +bool Image11::copyToStorageImpl(TextureStorage11 *storage11, int level, int layerTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) { - TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage->getStorageInstance()); - return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, arrayLayer, xoffset, yoffset, 0, width, height, 1); + // 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. + storage11->releaseAssociatedImage(level, layerTarget, this); + } + + bool updateSubresourceSuccess = storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, layerTarget, xoffset, yoffset, 0, width, height, 1); + + // Once the image data has been copied into the Storage, we can release it locally. + if (attemptToReleaseStagingTexture && updateSubresourceSuccess) + { + storage11->associateImage(this, level, layerTarget); + releaseStagingTexture(); + mRecoverFromStorage = true; + mAssociatedStorage = storage11; + mAssociatedStorageLevel = level; + mAssociatedStorageLayerTarget = layerTarget; + } + + return updateSubresourceSuccess; +} + +bool Image11::isAssociatedStorageValid(TextureStorage11* textureStorage) const +{ + return (mAssociatedStorage == textureStorage); +} + +bool Image11::recoverFromAssociatedStorage() +{ + if (mRecoverFromStorage) + { + createStagingTexture(); + + bool textureStorageCorrect = mAssociatedStorage->isAssociatedImageValid(mAssociatedStorageLevel, mAssociatedStorageLayerTarget, 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 + mAssociatedStorage->copySubresourceLevel(mStagingTexture, mStagingSubresource, mAssociatedStorageLevel, mAssociatedStorageLayerTarget, 0, 0, 0, mWidth, mHeight, mDepth); + mRecoveredFromStorageCount += 1; + } + + // Reset all the recovery parameters, even if the texture storage association is broken. + disassociateStorage(); + + return textureStorageCorrect; + } + + return false; +} + +void Image11::disassociateStorage() +{ + if (mRecoverFromStorage) + { + // Make the texturestorage release the Image11 too + mAssociatedStorage->disassociateImage(mAssociatedStorageLevel, mAssociatedStorageLayerTarget, this); + + mRecoverFromStorage = false; + mAssociatedStorage = NULL; + mAssociatedStorageLevel = 0; + mAssociatedStorageLayerTarget = 0; + } } bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) @@ -117,6 +207,11 @@ bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat, 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; @@ -126,12 +221,14 @@ bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat, mTarget = target; // compute the d3d format that will be used - mDXGIFormat = gl_d3d11::GetTexFormat(internalformat); - mActualFormat = d3d11_gl::GetInternalFormat(mDXGIFormat); - mRenderable = gl_d3d11::GetRTVFormat(internalformat) != DXGI_FORMAT_UNKNOWN; + 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); SafeRelease(mStagingTexture); - mDirty = gl_d3d11::RequiresTextureDataInitialization(mInternalFormat); + mDirty = (formatInfo.dataInitializerFunction != NULL); return true; } @@ -153,12 +250,15 @@ DXGI_FORMAT Image11::getDXGIFormat() const void Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLint unpackAlignment, GLenum type, const void *input) { - GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, type, width, unpackAlignment); - GLsizei inputDepthPitch = gl::GetDepthPitch(mInternalFormat, type, width, height, unpackAlignment); - GLuint outputPixelSize = d3d11::GetFormatPixelBytes(mDXGIFormat); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment); + GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpackAlignment); - LoadImageFunction loadFunction = d3d11::GetImageLoadFunction(mInternalFormat, type); - ASSERT(loadFunction != NULL); + 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; HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); @@ -179,18 +279,20 @@ void Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei widt void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, const void *input) { - GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, GL_UNSIGNED_BYTE, width, 1); - GLsizei inputDepthPitch = gl::GetDepthPitch(mInternalFormat, GL_UNSIGNED_BYTE, width, height, 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); - GLuint outputPixelSize = d3d11::GetFormatPixelBytes(mDXGIFormat); - GLuint outputBlockWidth = d3d11::GetBlockWidth(mDXGIFormat); - GLuint outputBlockHeight = d3d11::GetBlockHeight(mDXGIFormat); + 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); - LoadImageFunction loadFunction = d3d11::GetImageLoadFunction(mInternalFormat, GL_UNSIGNED_BYTE); - ASSERT(loadFunction != NULL); + const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat); + LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE); D3D11_MAPPED_SUBRESOURCE mappedImage; HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); @@ -287,13 +389,12 @@ void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y } // determine the offset coordinate into the destination buffer - GLsizei rowOffset = gl::GetPixelBytes(mActualFormat) * xoffset; - void *dataOffset = static_cast(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch; + GLsizei rowOffset = gl::GetInternalFormatInfo(mActualFormat).pixelBytes * xoffset; + uint8_t *dataOffset = static_cast(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch; - GLenum format = gl::GetFormat(mInternalFormat); - GLenum type = gl::GetType(mInternalFormat); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); - mRenderer->readPixels(source, x, y, width, height, format, type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset); + mRenderer->readPixels(source, x, y, width, height, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset); unmap(); } @@ -306,6 +407,11 @@ ID3D11Resource *Image11::getStagingTexture() return mStagingTexture; } +void Image11::releaseStagingTexture() +{ + SafeRelease(mStagingTexture); +} + unsigned int Image11::getStagingSubresource() { createStagingTexture(); @@ -349,7 +455,7 @@ void Image11::createStagingTexture() desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (gl_d3d11::RequiresTextureDataInitialization(mInternalFormat)) + if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) { std::vector initialData; std::vector< std::vector > textureData; @@ -390,7 +496,7 @@ void Image11::createStagingTexture() desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; desc.MiscFlags = 0; - if (gl_d3d11::RequiresTextureDataInitialization(mInternalFormat)) + if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) { std::vector initialData; std::vector< std::vector > textureData; @@ -427,6 +533,9 @@ HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) { createStagingTexture(); + // We must recover from the TextureStorage if necessary, even for D3D11_MAP_WRITE. + recoverFromAssociatedStorage(); + HRESULT result = E_FAIL; if (mStagingTexture) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h index 7d873a2794..a76a61f036 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h @@ -23,8 +23,7 @@ namespace rx { class Renderer; class Renderer11; -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; +class TextureStorage11; class Image11 : public ImageD3D { @@ -38,10 +37,10 @@ class Image11 : public ImageD3D virtual bool isDirty() const; - virtual bool copyToStorage(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - virtual bool copyToStorage(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - virtual bool copyToStorage(TextureStorageInterface3D *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); - virtual bool copyToStorage(TextureStorageInterface2DArray *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height); + virtual bool copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + virtual bool copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + virtual bool copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); + virtual bool copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, GLsizei width, GLsizei height); virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease); @@ -54,6 +53,10 @@ class Image11 : public ImageD3D virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + bool recoverFromAssociatedStorage(); + bool isAssociatedStorageValid(TextureStorage11* textureStorage) const; + void disassociateStorage(); + protected: HRESULT map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); void unmap(); @@ -61,15 +64,24 @@ class Image11 : public ImageD3D private: DISALLOW_COPY_AND_ASSIGN(Image11); + bool copyToStorageImpl(TextureStorage11 *storage11, int level, int layerTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + ID3D11Resource *getStagingTexture(); unsigned int getStagingSubresource(); void createStagingTexture(); + void releaseStagingTexture(); Renderer11 *mRenderer; DXGI_FORMAT mDXGIFormat; ID3D11Resource *mStagingTexture; unsigned int mStagingSubresource; + + bool mRecoverFromStorage; + TextureStorage11 *mAssociatedStorage; + int mAssociatedStorageLevel; + int mAssociatedStorageLayerTarget; + unsigned int mRecoveredFromStorageCount; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp index 03e4e6611b..9a61182ee9 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -25,7 +24,7 @@ IndexBuffer11::~IndexBuffer11() SafeRelease(mBuffer); } -bool IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) +gl::Error IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) { SafeRelease(mBuffer); @@ -46,7 +45,7 @@ bool IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool d HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); if (FAILED(result)) { - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize); } } @@ -54,7 +53,7 @@ bool IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool d mIndexType = indexType; mDynamicUsage = dynamic; - return true; + return gl::Error(GL_NO_ERROR); } IndexBuffer11 *IndexBuffer11::makeIndexBuffer11(IndexBuffer *indexBuffer) @@ -63,50 +62,42 @@ IndexBuffer11 *IndexBuffer11::makeIndexBuffer11(IndexBuffer *indexBuffer) return static_cast(indexBuffer); } -bool IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) +gl::Error IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) { - if (mBuffer) + if (!mBuffer) { - // Check for integer overflows and out-out-bounds map requests - if (offset + size < offset || offset + size > mBufferSize) - { - ERR("Index buffer map range is not inside the buffer."); - return false; - } + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + } - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + // 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."); + } - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Index buffer map failed with error 0x%08x", result); - return false; - } + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - *outMappedMemory = reinterpret_cast(mappedResource.pData) + offset; - return true; - } - else + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + if (FAILED(result)) { - ERR("Index buffer not initialized."); - return false; + 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); } -bool IndexBuffer11::unmapBuffer() +gl::Error IndexBuffer11::unmapBuffer() { - if (mBuffer) + if (!mBuffer) { - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - dxContext->Unmap(mBuffer, 0); - return true; - } - else - { - ERR("Index buffer not initialized."); - return false; + 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 @@ -119,7 +110,7 @@ unsigned int IndexBuffer11::getBufferSize() const return mBufferSize; } -bool IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType) +gl::Error IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType) { if (bufferSize > mBufferSize || indexType != mIndexType) { @@ -127,33 +118,29 @@ bool IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType) } else { - return true; + return gl::Error(GL_NO_ERROR); } } -bool IndexBuffer11::discard() +gl::Error IndexBuffer11::discard() { - if (mBuffer) + if (!mBuffer) { - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Index buffer map failed with error 0x%08x", result); - return false; - } + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + } - dxContext->Unmap(mBuffer, 0); + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - return true; - } - else + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) { - ERR("Index buffer not initialized."); - return false; + 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 @@ -172,4 +159,4 @@ ID3D11Buffer *IndexBuffer11::getBuffer() const return mBuffer; } -} \ No newline at end of file +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h index e821b7f3d1..f7c2b38e7e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h @@ -21,18 +21,18 @@ class IndexBuffer11 : public IndexBuffer explicit IndexBuffer11(Renderer11 *const renderer); virtual ~IndexBuffer11(); - virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); + virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); static IndexBuffer11 *makeIndexBuffer11(IndexBuffer *indexBuffer); - virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); - virtual bool unmapBuffer(); + virtual 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 bool setSize(unsigned int bufferSize, GLenum indexType); + virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType); - virtual bool discard(); + virtual gl::Error discard(); DXGI_FORMAT getIndexFormat() const; ID3D11Buffer *getBuffer() const; 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 3536fafac9..d835e4fa68 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -12,10 +11,10 @@ #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/VertexDataManager.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/renderer/d3d/VertexDataManager.h" -#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" #include "third_party/murmurhash/MurmurHash3.h" @@ -86,16 +85,15 @@ void InputLayoutCache::markDirty() } } -GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], - gl::ProgramBinary *programBinary) +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) { - ERR("InputLayoutCache is not initialized."); - return GL_INVALID_OPERATION; + return gl::Error(GL_OUT_OF_MEMORY, "Internal input layout cache is not initialized."); } InputLayoutKey ilKey = { 0 }; @@ -109,7 +107,7 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M 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); - DXGI_FORMAT dxgiFormat = gl_d3d11::GetNativeVertexFormat(vertexFormat); + 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 @@ -118,7 +116,7 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName; ilKey.elements[ilKey.elementCount].desc.SemanticIndex = i; - ilKey.elements[ilKey.elementCount].desc.Format = dxgiFormat; + 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; @@ -150,8 +148,7 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout); if (FAILED(result)) { - ERR("Failed to crate input layout, result: 0x%08x", result); - return GL_INVALID_OPERATION; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal input layout, HRESULT: 0x%08x", result); } if (mInputLayoutMap.size() >= kMaxInputLayouts) @@ -223,7 +220,7 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M mCurrentVertexStrides + minDiff, mCurrentVertexOffsets + minDiff); } - return GL_NO_ERROR; + return gl::Error(GL_NO_ERROR); } std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h index 5d0ac60537..cc71ac3f6f 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h @@ -11,8 +11,14 @@ #define LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ #include "libGLESv2/Constants.h" +#include "libGLESv2/Error.h" #include "common/angleutils.h" +#include + +#include +#include + namespace gl { class ProgramBinary; @@ -32,8 +38,8 @@ class InputLayoutCache void clear(); void markDirty(); - GLenum applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], - gl::ProgramBinary *programBinary); + gl::Error applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], + gl::ProgramBinary *programBinary); private: DISALLOW_COPY_AND_ASSIGN(InputLayoutCache); 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 07040342c7..a4e84f91c2 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -11,15 +10,15 @@ // #include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h" -#include "libGLESv2/formatutils.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Buffer.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 @@ -125,7 +124,7 @@ void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, cons float texelCenterX = 0.5f / static_cast(destSize.width - 1); float texelCenterY = 0.5f / static_cast(destSize.height - 1); - unsigned int bytesPerPixel = gl::GetPixelBytes(internalFormat); + unsigned int bytesPerPixel = gl::GetInternalFormatInfo(internalFormat).pixelBytes; unsigned int alignmentBytes = static_cast(unpack.alignment); unsigned int alignmentPixels = (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel); @@ -160,10 +159,11 @@ bool PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, un // 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::GetFormat(destinationFormat); - GLenum sourceFormat = gl::GetSizedInternalFormat(unsizedFormat, sourcePixelsType); + GLenum unsizedFormat = gl::GetInternalFormatInfo(destinationFormat).format; + GLenum sourceFormat = gl::GetFormatTypeInfo(unsizedFormat, sourcePixelsType).internalFormat; - DXGI_FORMAT srvFormat = gl_d3d11::GetSRVFormat(sourceFormat); + 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); @@ -239,8 +239,7 @@ void PixelTransfer11::buildShaderMap() ID3D11PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const { - GLenum componentType = gl::GetComponentType(internalFormat); - + GLenum componentType = gl::GetInternalFormatInfo(internalFormat).componentType; if (componentType == GL_SIGNED_NORMALIZED || componentType == GL_UNSIGNED_NORMALIZED) { componentType = GL_FLOAT; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h index 2e2fee8f50..ed1a3ae1d0 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h @@ -13,6 +13,10 @@ #include "common/platform.h" +#include + +#include + namespace gl { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp index e5e00325b2..7109be3e28 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -12,35 +11,18 @@ #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" #include "libGLESv2/main.h" -#if defined(__MINGW32__) // Provide undefined struct -typedef struct D3D11_QUERY_DATA_SO_STATISTICS -{ - UINT64 NumPrimitivesWritten; - UINT64 PrimitivesStorageNeeded; -} D3D11_QUERY_DATA_SO_STATISTICS; -#endif +#include namespace rx { -static bool checkOcclusionQuery(ID3D11DeviceContext *context, ID3D11Query *query, UINT64 *numPixels) -{ - HRESULT result = context->GetData(query, numPixels, sizeof(UINT64), 0); - return (result == S_OK); -} - -static bool checkStreamOutPrimitivesWritten(ID3D11DeviceContext *context, ID3D11Query *query, UINT64 *numPrimitives) -{ - D3D11_QUERY_DATA_SO_STATISTICS soStats = { 0 }; - HRESULT result = context->GetData(query, &soStats, sizeof(D3D11_QUERY_DATA_SO_STATISTICS), 0); - *numPrimitives = soStats.NumPrimitivesWritten; - return (result == S_OK); -} - -Query11::Query11(rx::Renderer11 *renderer, GLenum type) : QueryImpl(type) +Query11::Query11(rx::Renderer11 *renderer, GLenum type) + : QueryImpl(type), + mResult(0), + mQueryFinished(false), + mRenderer(renderer), + mQuery(NULL) { - mRenderer = renderer; - mQuery = NULL; } Query11::~Query11() @@ -48,7 +30,7 @@ Query11::~Query11() SafeRelease(mQuery); } -void Query11::begin() +gl::Error Query11::begin() { if (mQuery == NULL) { @@ -56,69 +38,85 @@ void Query11::begin() queryDesc.Query = gl_d3d11::ConvertQueryType(getType()); queryDesc.MiscFlags = 0; - if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) + HRESULT result = mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery); + if (FAILED(result)) { - return gl::error(GL_OUT_OF_MEMORY); + 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); } -void Query11::end() +gl::Error Query11::end() { ASSERT(mQuery); mRenderer->getDeviceContext()->End(mQuery); - mStatus = GL_FALSE; + mQueryFinished = false; mResult = GL_FALSE; + + return gl::Error(GL_NO_ERROR); } -GLuint Query11::getResult() +gl::Error Query11::getResult(GLuint *params) { - if (mQuery != NULL) + while (!mQueryFinished) { - while (!testQuery()) + gl::Error error = testQuery(); + if (error.isError()) + { + return error; + } + + if (!mQueryFinished) { Sleep(0); - // explicitly check for device loss, some drivers seem to return S_FALSE - // if the device is lost - if (mRenderer->testDeviceLost(true)) - { - return gl::error(GL_OUT_OF_MEMORY, 0); - } } } - return mResult; + ASSERT(mQueryFinished); + *params = mResult; + + return gl::Error(GL_NO_ERROR); } -GLboolean Query11::isResultAvailable() +gl::Error Query11::isResultAvailable(GLuint *available) { - if (mQuery != NULL) + gl::Error error = testQuery(); + if (error.isError()) { - testQuery(); + return error; } - return mStatus; + *available = (mQueryFinished ? GL_TRUE : GL_FALSE); + + return gl::Error(GL_NO_ERROR); } -GLboolean Query11::testQuery() +gl::Error Query11::testQuery() { - if (mQuery != NULL && mStatus != GL_TRUE) + if (!mQueryFinished) { - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + ASSERT(mQuery); - bool queryFinished = false; + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); switch (getType()) { case GL_ANY_SAMPLES_PASSED_EXT: case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: { UINT64 numPixels = 0; - queryFinished = checkOcclusionQuery(context, mQuery, &numPixels); - if (queryFinished) + 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; } } @@ -126,11 +124,17 @@ GLboolean Query11::testQuery() case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: { - UINT64 numPrimitives = 0; - queryFinished = checkStreamOutPrimitivesWritten(context, mQuery, &numPrimitives); - if (queryFinished) + 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) { - mResult = static_cast(numPrimitives); + mQueryFinished = true; + mResult = static_cast(soStats.NumPrimitivesWritten); } } break; @@ -140,24 +144,13 @@ GLboolean Query11::testQuery() break; } - if (queryFinished) - { - mStatus = GL_TRUE; - } - else if (mRenderer->testDeviceLost(true)) + if (!mQueryFinished && mRenderer->testDeviceLost(true)) { - return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost."); } - - return mStatus; } - return GL_TRUE; // prevent blocking when query is null -} - -bool Query11::isStarted() const -{ - return (mQuery != NULL); + 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 index 7a3df46d4f..822f2542ee 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h @@ -21,16 +21,19 @@ class Query11 : public QueryImpl Query11(rx::Renderer11 *renderer, GLenum type); virtual ~Query11(); - virtual void begin(); - virtual void end(); - virtual GLuint getResult(); - virtual GLboolean isResultAvailable(); - virtual bool isStarted() const; + 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); - GLboolean testQuery(); + gl::Error testQuery(); + + GLuint mResult; + + bool mQueryFinished; rx::Renderer11 *mRenderer; ID3D11Query *mQuery; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp index b185d97604..71b931f27e 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -15,6 +14,7 @@ #include "libGLESv2/FramebufferAttachment.h" #include "common/debug.h" + #include "third_party/murmurhash/MurmurHash3.h" namespace rx @@ -79,39 +79,37 @@ bool RenderStateCache::compareBlendStates(const BlendStateKey &a, const BlendSta return memcmp(&a, &b, sizeof(BlendStateKey)) == 0; } -ID3D11BlendState *RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState) +gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, + ID3D11BlendState **outBlendState) { if (!mDevice) { - ERR("RenderStateCache is not initialized."); - return NULL; + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); } bool mrt = false; + const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender(); + BlendStateKey key = { 0 }; key.blendState = blendState; - for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) { - const gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(i); + const gl::FramebufferAttachment *attachment = colorbuffers[colorAttachment]; + + auto rtChannels = key.rtChannels[colorAttachment]; + if (attachment) { - if (i > 0) + if (colorAttachment > 0) { mrt = true; } - key.rtChannels[i][0] = attachment->getRedSize() > 0; - key.rtChannels[i][1] = attachment->getGreenSize() > 0; - key.rtChannels[i][2] = attachment->getBlueSize() > 0; - key.rtChannels[i][3] = attachment->getAlphaSize() > 0; - } - else - { - key.rtChannels[i][0] = false; - key.rtChannels[i][1] = false; - key.rtChannels[i][2] = false; - key.rtChannels[i][3] = false; + rtChannels[0] = attachment->getRedSize() > 0; + rtChannels[1] = attachment->getGreenSize() > 0; + rtChannels[2] = attachment->getBlueSize() > 0; + rtChannels[3] = attachment->getAlphaSize() > 0; } } @@ -120,7 +118,8 @@ ID3D11BlendState *RenderStateCache::getBlendState(const gl::Framebuffer *framebu { BlendStateCounterPair &state = keyIter->second; state.second = mCounter++; - return state.first; + *outBlendState = state.first; + return gl::Error(GL_NO_ERROR); } else { @@ -172,13 +171,13 @@ ID3D11BlendState *RenderStateCache::getBlendState(const gl::Framebuffer *framebu HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState); if (FAILED(result) || !dx11BlendState) { - ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); - return NULL; + 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++))); - return dx11BlendState; + *outBlendState = dx11BlendState; + return gl::Error(GL_NO_ERROR); } } @@ -196,12 +195,12 @@ bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, cons return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0; } -ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled) +gl::Error RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled, + ID3D11RasterizerState **outRasterizerState) { if (!mDevice) { - ERR("RenderStateCache is not initialized."); - return NULL; + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); } RasterizerStateKey key = { 0 }; @@ -213,7 +212,8 @@ ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::Rasterizer { RasterizerStateCounterPair &state = keyIter->second; state.second = mCounter++; - return state.first; + *outRasterizerState = state.first; + return gl::Error(GL_NO_ERROR); } else { @@ -267,13 +267,13 @@ ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::Rasterizer HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState); if (FAILED(result) || !dx11RasterizerState) { - ERR("Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result); - return NULL; + 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++))); - return dx11RasterizerState; + *outRasterizerState = dx11RasterizerState; + return gl::Error(GL_NO_ERROR); } } @@ -291,12 +291,11 @@ bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a, return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0; } -ID3D11DepthStencilState *RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState) +gl::Error RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState, ID3D11DepthStencilState **outDSState) { if (!mDevice) { - ERR("RenderStateCache is not initialized."); - return NULL; + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); } DepthStencilStateMap::iterator keyIter = mDepthStencilStateCache.find(dsState); @@ -304,7 +303,8 @@ ID3D11DepthStencilState *RenderStateCache::getDepthStencilState(const gl::DepthS { DepthStencilStateCounterPair &state = keyIter->second; state.second = mCounter++; - return state.first; + *outDSState = state.first; + return gl::Error(GL_NO_ERROR); } else { @@ -345,13 +345,13 @@ ID3D11DepthStencilState *RenderStateCache::getDepthStencilState(const gl::DepthS HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState); if (FAILED(result) || !dx11DepthStencilState) { - ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); - return NULL; + 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++))); - return dx11DepthStencilState; + *outDSState = dx11DepthStencilState; + return gl::Error(GL_NO_ERROR); } } @@ -369,12 +369,11 @@ bool RenderStateCache::compareSamplerStates(const gl::SamplerState &a, const gl: return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0; } -ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &samplerState) +gl::Error RenderStateCache::getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState) { if (!mDevice) { - ERR("RenderStateCache is not initialized."); - return NULL; + return gl::Error(GL_OUT_OF_MEMORY, "Internal error, RenderStateCache is not initialized."); } SamplerStateMap::iterator keyIter = mSamplerStateCache.find(samplerState); @@ -382,7 +381,8 @@ ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &sa { SamplerStateCounterPair &state = keyIter->second; state.second = mCounter++; - return state.first; + *outSamplerState = state.first; + return gl::Error(GL_NO_ERROR); } else { @@ -423,13 +423,13 @@ ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &sa HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState); if (FAILED(result) || !dx11SamplerState) { - ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); - return NULL; + 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++))); - return dx11SamplerState; + *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 index e6380fbd82..d5471a3061 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h @@ -11,8 +11,11 @@ #define LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ #include "libGLESv2/angletypes.h" +#include "libGLESv2/Error.h" #include "common/angleutils.h" +#include + namespace gl { class Framebuffer; @@ -31,10 +34,10 @@ class RenderStateCache void initialize(ID3D11Device *device); void clear(); - ID3D11BlendState *getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState); - ID3D11RasterizerState *getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled); - ID3D11DepthStencilState *getDepthStencilState(const gl::DepthStencilState &dsState); - ID3D11SamplerState *getSamplerState(const gl::SamplerState &samplerState); + 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); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp index 6aa75ae5bd..3041f21faa 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -10,7 +9,6 @@ #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/formatutils11.h" #include "libGLESv2/main.h" @@ -219,8 +217,9 @@ RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, mDepth = depth; mSamples = samples; - mInternalFormat = d3d11_gl::GetInternalFormat(desc.Format); - mActualFormat = d3d11_gl::GetInternalFormat(desc.Format); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format); + mInternalFormat = dxgiFormatInfo.internalFormat; + mActualFormat = dxgiFormatInfo.internalFormat; } } @@ -265,8 +264,9 @@ RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, mDepth = depth; mSamples = samples; - mInternalFormat = d3d11_gl::GetInternalFormat(desc.Format); - mActualFormat = d3d11_gl::GetInternalFormat(desc.Format); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format); + mInternalFormat = dxgiFormatInfo.internalFormat; + mActualFormat = dxgiFormatInfo.internalFormat; } } @@ -278,18 +278,11 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height mDepthStencil = NULL; mShaderResource = NULL; - DXGI_FORMAT texFormat = gl_d3d11::GetTexFormat(internalFormat); - DXGI_FORMAT srvFormat = gl_d3d11::GetSRVFormat(internalFormat); - DXGI_FORMAT rtvFormat = gl_d3d11::GetRTVFormat(internalFormat); - DXGI_FORMAT dsvFormat = gl_d3d11::GetDSVFormat(internalFormat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat); + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat); - DXGI_FORMAT multisampleFormat = (dsvFormat != DXGI_FORMAT_UNKNOWN ? dsvFormat : rtvFormat); - int supportedSamples = mRenderer->getNearestSupportedSamples(multisampleFormat, samples); - if (supportedSamples < 0) - { - gl::error(GL_OUT_OF_MEMORY); - return; - } + const gl::TextureCaps &textureCaps = mRenderer->getRendererTextureCaps().get(internalFormat); + GLuint supportedSamples = textureCaps.getNearestSamples(samples); if (width > 0 && height > 0) { @@ -299,7 +292,7 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height desc.Height = height; desc.MipLevels = 1; desc.ArraySize = 1; - desc.Format = texFormat; + desc.Format = formatInfo.texFormat; desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; desc.SampleDesc.Quality = 0; desc.Usage = D3D11_USAGE_DEFAULT; @@ -310,14 +303,14 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height // 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 = (rtvFormat != DXGI_FORMAT_UNKNOWN); - bindDSV = (dsvFormat != DXGI_FORMAT_UNKNOWN); - if (srvFormat != DXGI_FORMAT_UNKNOWN) + 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 = !(dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1); + bindSRV = !(formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN && desc.SampleDesc.Count > 1); } desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) | @@ -339,7 +332,7 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height if (bindSRV) { D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = srvFormat; + srvDesc.Format = formatInfo.srvFormat; srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; srvDesc.Texture2D.MostDetailedMip = 0; srvDesc.Texture2D.MipLevels = 1; @@ -357,7 +350,7 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height if (bindDSV) { D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = dsvFormat; + dsvDesc.Format = formatInfo.dsvFormat; dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; dsvDesc.Texture2D.MipSlice = 0; dsvDesc.Flags = 0; @@ -376,7 +369,7 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height if (bindRTV) { D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = rtvFormat; + rtvDesc.Format = formatInfo.rtvFormat; rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; rtvDesc.Texture2D.MipSlice = 0; result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget); @@ -391,7 +384,7 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height } ASSERT(SUCCEEDED(result)); - if (gl_d3d11::RequiresTextureDataInitialization(internalFormat)) + if (formatInfo.dataInitializerFunction != NULL) { ID3D11DeviceContext *context = mRenderer->getDeviceContext(); @@ -401,12 +394,13 @@ RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height } } + mWidth = width; mHeight = height; mDepth = 1; mInternalFormat = internalFormat; mSamples = supportedSamples; - mActualFormat = d3d11_gl::GetInternalFormat(texFormat); + mActualFormat = dxgiFormatInfo.internalFormat; mSubresourceIndex = D3D11CalcSubresource(0, 0, 1); } 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 3ba0cc767b..b29b2ef910 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -7,14 +6,16 @@ // Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. -#include "libGLESv2/main.h" -#include "common/utilities.h" #include "common/platform.h" +#include "libGLESv2/main.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Framebuffer.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" @@ -35,8 +36,15 @@ #include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h" #include "libGLESv2/renderer/d3d/d3d11/VertexArray11.h" #include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" + #include "libEGL/Display.h" +#include "common/utilities.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 @@ -49,31 +57,6 @@ #define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1 #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 -#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT -# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14 -#endif -#ifndef D3D11_SO_BUFFER_SLOT_COUNT -# define D3D11_SO_BUFFER_SLOT_COUNT 4 -#endif -#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT -# define D3D10_1_SO_BUFFER_SLOT_COUNT 4 -#endif -#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT -# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096 -#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 - namespace rx { static const DXGI_FORMAT RenderTargetFormats[] = @@ -117,8 +100,6 @@ Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, EGLint r mDeviceLost = false; - mMaxSupportedSamples = 0; - mDevice = NULL; mDeviceContext = NULL; mDxgiAdapter = NULL; @@ -320,16 +301,6 @@ EGLint Renderer11::initialize() } #endif - mMaxSupportedSamples = 0; - - const d3d11::DXGIFormatSet &dxgiFormats = d3d11::GetAllUsedDXGIFormats(); - for (d3d11::DXGIFormatSet::const_iterator i = dxgiFormats.begin(); i != dxgiFormats.end(); ++i) - { - MultisampleSupportInfo support = getMultisampleSupportInfo(*i); - mMultisampleSupportMap.insert(std::make_pair(*i, support)); - mMaxSupportedSamples = std::max(mMaxSupportedSamples, support.maxSupportedSamples); - } - #if !defined(ANGLE_PLATFORM_WINRT) static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED"); if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1")) @@ -369,6 +340,17 @@ void Renderer11::initializeDevice() 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(); } @@ -378,34 +360,22 @@ int Renderer11::generateConfigs(ConfigDesc **configDescList) unsigned int numDepthFormats = ArraySize(DepthStencilFormats); (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; int numConfigs = 0; - + for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) { - for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) + const d3d11::DXGIFormat &renderTargetFormatInfo = d3d11::GetDXGIFormatInfo(RenderTargetFormats[formatIndex]); + const gl::TextureCaps &renderTargetFormatCaps = getRendererTextureCaps().get(renderTargetFormatInfo.internalFormat); + if (renderTargetFormatCaps.renderable) { - DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex]; - - UINT formatSupport = 0; - HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport); - - if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) + for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) { - DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; - - bool depthStencilFormatOK = true; - - if (depthStencilFormat != DXGI_FORMAT_UNKNOWN) - { - UINT depthStencilSupport = 0; - result = mDevice->CheckFormatSupport(depthStencilFormat, &depthStencilSupport); - depthStencilFormatOK = SUCCEEDED(result) && (depthStencilSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL); - } - - if (depthStencilFormatOK) + 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 = d3d11_gl::GetInternalFormat(renderTargetFormat); - newConfig.depthStencilFormat = d3d11_gl::GetInternalFormat(depthStencilFormat); + 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; @@ -468,43 +438,45 @@ SwapChain *Renderer11::createSwapChain(EGLNativeWindowType window, HANDLE shareH return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat); } -void Renderer11::generateSwizzle(gl::Texture *texture) +gl::Error Renderer11::generateSwizzle(gl::Texture *texture) { if (texture) { - TextureStorageInterface *texStorage = texture->getNativeTexture(); + TextureStorage *texStorage = texture->getNativeTexture(); if (texStorage) { - TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance()); + TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage); - storage11->generateSwizzles(texture->getSamplerState().swizzleRed, - texture->getSamplerState().swizzleGreen, - texture->getSamplerState().swizzleBlue, - texture->getSamplerState().swizzleAlpha); + 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); } -void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) +gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) { if (type == gl::SAMPLER_PIXEL) { - if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS) - { - ERR("Pixel shader sampler index %i is not valid.", index); - return; - } + ASSERT(static_cast(index) < getRendererCaps().maxTextureImageUnits); if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) { - ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState); - - if (!dxSamplerState) + ID3D11SamplerState *dxSamplerState = NULL; + gl::Error error = mStateCache.getSamplerState(samplerState, &dxSamplerState); + if (error.isError()) { - ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default" - "sampler state for pixel shaders at slot %i.", index); + return error; } + ASSERT(dxSamplerState != NULL); mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState); mCurPixelSamplerStates[index] = samplerState; @@ -514,22 +486,18 @@ void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::Samp } else if (type == gl::SAMPLER_VERTEX) { - if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) - { - ERR("Vertex shader sampler index %i is not valid.", index); - return; - } + ASSERT(static_cast(index) < getRendererCaps().maxVertexTextureImageUnits); if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) { - ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState); - - if (!dxSamplerState) + ID3D11SamplerState *dxSamplerState = NULL; + gl::Error error = mStateCache.getSamplerState(samplerState, &dxSamplerState); + if (error.isError()) { - ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default" - "sampler state for vertex shaders at slot %i.", index); + return error; } + ASSERT(dxSamplerState != NULL); mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState); mCurVertexSamplerStates[index] = samplerState; @@ -538,38 +506,37 @@ void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::Samp mForceSetVertexSamplerStates[index] = false; } else UNREACHABLE(); + + return gl::Error(GL_NO_ERROR); } -void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture) +gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture) { ID3D11ShaderResourceView *textureSRV = NULL; bool forceSetTexture = false; if (texture) { - TextureStorageInterface *texStorage = texture->getNativeTexture(); - if (texStorage) - { - TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance()); - gl::SamplerState samplerState; - texture->getSamplerStateWithNativeOffset(&samplerState); - textureSRV = storage11->getSRV(samplerState); - } + TextureD3D* textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation()); + TextureStorage *texStorage = textureImpl->getNativeTexture(); + ASSERT(texStorage != NULL); + + TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage); + gl::SamplerState samplerState; + texture->getSamplerStateWithNativeOffset(&samplerState); + textureSRV = storage11->getSRV(samplerState); // 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); - forceSetTexture = texture->hasDirtyImages(); + forceSetTexture = textureImpl->hasDirtyImages(); + textureImpl->resetDirty(); } if (type == gl::SAMPLER_PIXEL) { - if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS) - { - ERR("Pixel shader sampler index %i is not valid.", index); - return; - } + ASSERT(static_cast(index) < getRendererCaps().maxTextureImageUnits); if (forceSetTexture || mCurPixelSRVs[index] != textureSRV) { @@ -580,11 +547,7 @@ void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *textur } else if (type == gl::SAMPLER_VERTEX) { - if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) - { - ERR("Vertex shader sampler index %i is not valid.", index); - return; - } + ASSERT(static_cast(index) < getRendererCaps().maxVertexTextureImageUnits); if (forceSetTexture || mCurVertexSRVs[index] != textureSRV) { @@ -594,9 +557,11 @@ void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *textur mCurVertexSRVs[index] = textureSRV; } else UNREACHABLE(); + + return gl::Error(GL_NO_ERROR); } -bool Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) +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++) { @@ -608,7 +573,7 @@ bool Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], con if (!constantBuffer) { - return false; + return gl::Error(GL_OUT_OF_MEMORY); } if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial()) @@ -630,7 +595,7 @@ bool Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], con if (!constantBuffer) { - return false; + return gl::Error(GL_OUT_OF_MEMORY); } if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial()) @@ -642,18 +607,18 @@ bool Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], con } } - return true; + return gl::Error(GL_NO_ERROR); } -void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) +gl::Error Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) { if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0) { - ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled); - if (!dxRasterState) + ID3D11RasterizerState *dxRasterState = NULL; + gl::Error error = mStateCache.getRasterizerState(rasterState, mScissorEnabled, &dxRasterState); + if (error.isError()) { - ERR("NULL rasterizer state returned by RenderStateCache::getRasterizerState, setting the default" - "rasterizer state."); + return error; } mDeviceContext->RSSetState(dxRasterState); @@ -662,23 +627,27 @@ void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) } mForceSetRasterState = false; + + return gl::Error(GL_NO_ERROR); } -void Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) +gl::Error Renderer11::setBlendState(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 = mStateCache.getBlendState(framebuffer, blendState); - if (!dxBlendState) + ID3D11BlendState *dxBlendState = NULL; + gl::Error error = mStateCache.getBlendState(framebuffer, blendState, &dxBlendState); + if (error.isError()) { - ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default " - "blend state."); + 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) @@ -704,10 +673,12 @@ void Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendStat } mForceSetBlendState = false; + + return gl::Error(GL_NO_ERROR); } -void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW) +gl::Error Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW) { if (mForceSetDepthStencilState || memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 || @@ -717,13 +688,15 @@ void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilS ASSERT(stencilRef == stencilBackRef); ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask); - ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState); - if (!dxDepthStencilState) + ID3D11DepthStencilState *dxDepthStencilState = NULL; + gl::Error error = mStateCache.getDepthStencilState(depthStencilState, &dxDepthStencilState); + if (error.isError()) { - ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, " - "setting the default depth stencil state."); + 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); @@ -738,6 +711,8 @@ void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilS } mForceSetDepthStencilState = false; + + return gl::Error(GL_NO_ERROR); } void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) @@ -768,7 +743,7 @@ void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) mForceSetScissor = false; } -bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, +void Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, bool ignoreViewport) { gl::Rectangle actualViewport = viewport; @@ -795,11 +770,6 @@ bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float z dxViewport.MinDepth = actualZNear; dxViewport.MaxDepth = actualZFar; - if (dxViewport.Width <= 0 || dxViewport.Height <= 0) - { - return false; // Nothing to render - } - bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || actualZNear != mCurNear || actualZFar != mCurFar; @@ -829,7 +799,6 @@ bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float z } mForceSetViewport = false; - return true; } bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) @@ -862,7 +831,7 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) return count >= minCount; } -bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) +gl::Error Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) { // Get the color render buffer and serial // Also extract the render target dimensions and view @@ -873,39 +842,37 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; bool missingColorRenderTarget = true; - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender(); + + for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) { - const GLenum drawBufferState = framebuffer->getDrawBufferState(colorAttachment); - gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(colorAttachment); + gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; - if (colorbuffer && drawBufferState != GL_NONE) + if (colorbuffer) { // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order) - ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment)); // check for zero-sized default framebuffer, which is a special case. // in this case we do not wish to modify any state and just silently return false. // this will not report any gl error but will cause the calling method to return. if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) { - return false; + return gl::Error(GL_NO_ERROR); } - renderTargetSerials[colorAttachment] = colorbuffer->getSerial(); + renderTargetSerials[colorAttachment] = GetAttachmentSerial(colorbuffer); // Extract the render target dimensions and view - RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer); if (!renderTarget) { - ERR("render target pointer unexpectedly null."); - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Internal render target pointer unexpectedly null."); } framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); if (!framebufferRTVs[colorAttachment]) { - ERR("render target view pointer unexpectedly null."); - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null."); } if (missingColorRenderTarget) @@ -921,37 +888,35 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) } } - // Get the depth stencil render buffer and serials + // Get the depth stencil render buffter and serials gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer(); unsigned int depthbufferSerial = 0; unsigned int stencilbufferSerial = 0; if (depthStencil) { - depthbufferSerial = depthStencil->getSerial(); + depthbufferSerial = GetAttachmentSerial(depthStencil); } else if (framebuffer->getStencilbuffer()) { depthStencil = framebuffer->getStencilbuffer(); - stencilbufferSerial = depthStencil->getSerial(); + stencilbufferSerial = GetAttachmentSerial(depthStencil); } ID3D11DepthStencilView* framebufferDSV = NULL; if (depthStencil) { - RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil()); + RenderTarget11 *depthStencilRenderTarget = d3d11::GetAttachmentRenderTarget(depthStencil); if (!depthStencilRenderTarget) { - ERR("render target pointer unexpectedly null."); SafeRelease(framebufferRTVs); - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Internal render target pointer unexpectedly null."); } framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); if (!framebufferDSV) { - ERR("depth stencil view pointer unexpectedly null."); SafeRelease(framebufferRTVs); - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null."); } // If there is no render buffer, the width, height and format values come from @@ -996,54 +961,54 @@ bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) invalidateFramebufferSwizzles(framebuffer); - return true; + return gl::Error(GL_NO_ERROR); } -GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], - GLint first, GLsizei count, GLsizei instances) +gl::Error Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], + GLint first, GLsizei count, GLsizei instances) { TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; - GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances); - if (err != GL_NO_ERROR) + gl::Error error = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances); + if (error.isError()) { - return err; + return error; } return mInputLayoutCache.applyVertexBuffers(attributes, programBinary); } -GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) +gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) { - GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); - - if (err == GL_NO_ERROR) + gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); + if (error.isError()) { - IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); + return error; + } - ID3D11Buffer *buffer = NULL; - DXGI_FORMAT bufferFormat = indexBuffer->getIndexFormat(); + 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 - { - buffer = indexBuffer->getBuffer(); - } + 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); + if (buffer != mAppliedIB || bufferFormat != mAppliedIBFormat || indexInfo->startOffset != mAppliedIBOffset) + { + mDeviceContext->IASetIndexBuffer(buffer, bufferFormat, indexInfo->startOffset); - mAppliedIB = buffer; - mAppliedIBFormat = bufferFormat; - mAppliedIBOffset = indexInfo->startOffset; - } + mAppliedIB = buffer; + mAppliedIBFormat = bufferFormat; + mAppliedIBOffset = indexInfo->startOffset; } - return err; + return gl::Error(GL_NO_ERROR); } void Renderer11::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) @@ -1084,7 +1049,7 @@ void Renderer11::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuff } } -void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) +gl::Error Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) { if (mode == GL_POINTS && transformFeedbackActive) { @@ -1117,43 +1082,51 @@ void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool } mDeviceContext->GSSetShader(mAppliedGeometryShader, NULL, 0); + + return gl::Error(GL_NO_ERROR); } else if (mode == GL_LINE_LOOP) { - drawLineLoop(count, GL_NONE, NULL, 0, NULL); + return drawLineLoop(count, GL_NONE, NULL, 0, NULL); } else if (mode == GL_TRIANGLE_FAN) { - drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances); + 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); } } -void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) +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) { - drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); + return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer); } else if (mode == GL_TRIANGLE_FAN) { - drawTriangleFan(count, type, indices, indexInfo.minIndex, elementArrayBuffer, instances); + return drawTriangleFan(count, type, indices, minIndex, elementArrayBuffer, instances); } else if (instances > 0) { - mDeviceContext->DrawIndexedInstanced(count, instances, 0, -static_cast(indexInfo.minIndex), 0); + mDeviceContext->DrawIndexedInstanced(count, instances, 0, -minIndex, 0); + return gl::Error(GL_NO_ERROR); } else { - mDeviceContext->DrawIndexed(count, 0, -static_cast(indexInfo.minIndex)); + mDeviceContext->DrawIndexed(count, 0, -minIndex); + return gl::Error(GL_NO_ERROR); } } @@ -1235,7 +1208,7 @@ static void fillTriangleFanIndices(GLenum type, unsigned int numTris, const GLvo } } -void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +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) @@ -1252,13 +1225,11 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, if (!mLineLoopIB) { mLineLoopIB = new StreamingIndexBufferInterface(this); - if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType)) + gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType); + if (error.isError()) { - delete mLineLoopIB; - mLineLoopIB = NULL; - - ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); + SafeDelete(mLineLoopIB); + return error; } } @@ -1268,23 +1239,22 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int indexTypeSize = indexType == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int); if (static_cast(count) + 1 > (std::numeric_limits::max() / indexTypeSize)) { - ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); - return gl::error(GL_OUT_OF_MEMORY); + 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) * indexTypeSize; - if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, indexType)) + const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); + gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); + if (error.isError()) { - ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); + return error; } void* mappedMemory = NULL; unsigned int offset; - if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) + error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); + if (error.isError()) { - ERR("Could not map index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); + return error; } if (indexType == GL_UNSIGNED_SHORT) @@ -1293,10 +1263,10 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, fillLineLoopIndices(type, count, indices, reinterpret_cast(mappedMemory)); unsigned int indexBufferOffset = offset; - if (!mLineLoopIB->unmapBuffer()) + error = mLineLoopIB->unmapBuffer(); + if (error.isError()) { - ERR("Could not unmap index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); + return error; } IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer()); @@ -1305,16 +1275,18 @@ void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) { - mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); + mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset); mAppliedIB = d3dIndexBuffer; mAppliedIBFormat = indexFormat; mAppliedIBOffset = indexBufferOffset; } mDeviceContext->DrawIndexed(count + 1, 0, -minIndex); + + return gl::Error(GL_NO_ERROR); } -void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances) +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) @@ -1330,13 +1302,11 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic if (!mTriangleFanIB) { mTriangleFanIB = new StreamingIndexBufferInterface(this); - if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType)) + gl::Error error = mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType); + if (error.isError()) { - delete mTriangleFanIB; - mTriangleFanIB = NULL; - - ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN."); - return gl::error(GL_OUT_OF_MEMORY); + SafeDelete(mTriangleFanIB); + return error; } } @@ -1348,35 +1318,35 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic int indexTypeSize = indexType == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int); if (numTris > (std::numeric_limits::max() / (indexTypeSize * 3))) { - ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required."); - return gl::error(GL_OUT_OF_MEMORY); + 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; - if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, indexType)) + gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, indexType); + if (error.isError()) { - ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN."); - return gl::error(GL_OUT_OF_MEMORY); + return error; } void* mappedMemory = NULL; unsigned int offset; - if (!mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) + error = mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); + if (error.isError()) { - ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN."); - return gl::error(GL_OUT_OF_MEMORY); + 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; - if (!mTriangleFanIB->unmapBuffer()) + error = mTriangleFanIB->unmapBuffer(); + if (error.isError()) { - ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN."); - return gl::error(GL_OUT_OF_MEMORY); + return error; } IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer()); @@ -1385,7 +1355,7 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) { - mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); + mDeviceContext->IASetIndexBuffer(d3dIndexBuffer, indexFormat, indexBufferOffset); mAppliedIB = d3dIndexBuffer; mAppliedIBFormat = indexFormat; mAppliedIBOffset = indexBufferOffset; @@ -1399,10 +1369,12 @@ void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indic { mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex); } + + return gl::Error(GL_NO_ERROR); } -void Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, bool transformFeedbackActive) +gl::Error Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive) { ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout); ShaderExecutable *pixelExe = programBinary->getPixelExecutableForFramebuffer(framebuffer); @@ -1463,9 +1435,11 @@ void Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::Vertex { programBinary->dirtyAllUniforms(); } + + return gl::Error(GL_NO_ERROR); } -void Renderer11::applyUniforms(const gl::ProgramBinary &programBinary) +gl::Error Renderer11::applyUniforms(const gl::ProgramBinary &programBinary) { const std::vector &uniformArray = programBinary.getUniforms(); @@ -1492,8 +1466,9 @@ void Renderer11::applyUniforms(const gl::ProgramBinary &programBinary) } } - const UniformStorage11 *vertexUniformStorage = UniformStorage11::makeUniformStorage11(&programBinary.getVertexUniformStorage()); - const UniformStorage11 *fragmentUniformStorage = UniformStorage11::makeUniformStorage11(&programBinary.getFragmentUniformStorage()); + const ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary.getImplementation()); + const UniformStorage11 *vertexUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getVertexUniformStorage()); + const UniformStorage11 *fragmentUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getFragmentUniformStorage()); ASSERT(vertexUniformStorage); ASSERT(fragmentUniformStorage); @@ -1619,12 +1594,21 @@ void Renderer11::applyUniforms(const gl::ProgramBinary &programBinary) mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; } + + return gl::Error(GL_NO_ERROR); } -void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) +gl::Error Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) { - mClear->clearFramebuffer(clearParams, frameBuffer); + gl::Error error = mClear->clearFramebuffer(clearParams, frameBuffer); + if (error.isError()) + { + return error; + } + invalidateFramebufferSwizzles(frameBuffer); + + return gl::Error(GL_NO_ERROR); } void Renderer11::markAllStateDirty() @@ -1638,15 +1622,18 @@ void Renderer11::markAllStateDirty() mDepthStencilInitialized = false; mRenderTargetDescInitialized = false; - for (int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) + ASSERT(mForceSetVertexSamplerStates.size() == mCurVertexSRVs.size()); + for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId) { - mForceSetVertexSamplerStates[i] = true; - mCurVertexSRVs[i] = NULL; + mForceSetVertexSamplerStates[vsamplerId] = true; + mCurVertexSRVs[vsamplerId] = NULL; } - for (int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++) + + ASSERT(mForceSetPixelSamplerStates.size() == mCurPixelSRVs.size()); + for (size_t fsamplerId = 0; fsamplerId < mForceSetPixelSamplerStates.size(); ++fsamplerId) { - mForceSetPixelSamplerStates[i] = true; - mCurPixelSRVs[i] = NULL; + mForceSetPixelSamplerStates[fsamplerId] = true; + mCurPixelSRVs[fsamplerId] = NULL; } mForceSetBlendState = true; @@ -1803,6 +1790,7 @@ bool Renderer11::testDeviceResettable() void Renderer11::release() { + releaseShaderCompiler(); releaseDeviceResources(); SafeRelease(mDxgiFactory); @@ -1877,29 +1865,6 @@ GUID Renderer11::getAdapterIdentifier() const return adapterId; } -unsigned int Renderer11::getMaxVertexTextureImageUnits() const -{ - META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return 0; - default: UNREACHABLE(); - return 0; - } -} - -unsigned int Renderer11::getMaxCombinedTextureImageUnits() const -{ - return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits(); -} - unsigned int Renderer11::getReservedVertexUniformVectors() const { return 0; // Driver uniforms are stored in a separate constant buffer @@ -1910,85 +1875,6 @@ unsigned int Renderer11::getReservedFragmentUniformVectors() const return 0; // Driver uniforms are stored in a separate constant buffer } -unsigned int Renderer11::getMaxVertexUniformVectors() const -{ - META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); - ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1); - return MAX_VERTEX_UNIFORM_VECTORS_D3D11; -} - -unsigned int Renderer11::getMaxFragmentUniformVectors() const -{ - META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); - ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1); - return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11; -} - -unsigned int Renderer11::getMaxVaryingVectors() const -{ - META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT); - META_ASSERT(D3D11_VS_OUTPUT_REGISTER_COUNT <= D3D11_PS_INPUT_REGISTER_COUNT); - META_ASSERT(D3D10_VS_OUTPUT_REGISTER_COUNT <= D3D10_PS_INPUT_REGISTER_COUNT); - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - return D3D11_VS_OUTPUT_REGISTER_COUNT - getReservedVaryings(); - case D3D_FEATURE_LEVEL_10_1: - return D3D10_1_VS_OUTPUT_REGISTER_COUNT - getReservedVaryings(); - case D3D_FEATURE_LEVEL_10_0: - return D3D10_VS_OUTPUT_REGISTER_COUNT - getReservedVaryings(); - case D3D_FEATURE_LEVEL_9_3: - return 10 - getReservedVaryings(); - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return 8 - getReservedVaryings(); - default: UNREACHABLE(); - return 0; - } -} - -unsigned int Renderer11::getMaxVertexShaderUniformBuffers() const -{ - META_ASSERT(gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS >= D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT && - gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS >= D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); - - switch (mFeatureLevel) - { - 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(); - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return 0; - default: UNREACHABLE(); - return 0; - } -} - -unsigned int Renderer11::getMaxFragmentShaderUniformBuffers() const -{ - META_ASSERT(gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS >= D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT && - gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS >= D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT); - - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedFragmentUniformBuffers(); - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - getReservedFragmentUniformBuffers(); - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return 0; - default: UNREACHABLE(); - return 0; - } -} - unsigned int Renderer11::getReservedVertexUniformBuffers() const { // we reserve one buffer for the application uniforms, and one for driver uniforms @@ -2001,81 +1887,6 @@ unsigned int Renderer11::getReservedFragmentUniformBuffers() const return 2; } -unsigned int Renderer11::getReservedVaryings() const -{ - // We potentially reserve varyings for gl_Position, dx_Position, gl_FragCoord and gl_PointSize - return 4; -} - - -unsigned int Renderer11::getMaxTransformFeedbackBuffers() const -{ - META_ASSERT(gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS >= D3D11_SO_BUFFER_SLOT_COUNT && - gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS >= D3D10_SO_BUFFER_SLOT_COUNT); - - switch (mFeatureLevel) - { - 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; - } -} - -unsigned int Renderer11::getMaxTransformFeedbackSeparateComponents() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - return getMaxTransformFeedbackInterleavedComponents() / getMaxTransformFeedbackBuffers(); - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - // D3D 10 and 10.1 only allow one output per output slot if an output slot other than zero - // is used. - 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; - } -} - -unsigned int Renderer11::getMaxTransformFeedbackInterleavedComponents() const -{ - return (getMaxVaryingVectors() * 4); -} - -unsigned int Renderer11::getMaxUniformBufferSize() const -{ - // Each component is a 4-element vector of 4-byte units (floats) - const unsigned int bytesPerComponent = 4 * sizeof(float); - - switch (mFeatureLevel) - { - 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; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return 0; - default: UNREACHABLE(); - return 0; - } -} - bool Renderer11::getShareHandleSupport() const { // We only currently support share handles with BGRA surfaces, because @@ -2090,29 +1901,6 @@ bool Renderer11::getPostSubBufferSupport() const return false; } -int Renderer11::getMaxRecommendedElementsIndices() const -{ - META_ASSERT(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32); - META_ASSERT(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32); - - // D3D11 allows up to 2^32 elements, but we report max signed int for convenience. - return std::numeric_limits::max(); -} - -int Renderer11::getMaxRecommendedElementsVertices() const -{ - META_ASSERT(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32); - META_ASSERT(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32); - - // D3D11 allows up to 2^32 elements, but we report max signed int for convenience. - return std::numeric_limits::max(); -} - -bool Renderer11::getSRGBTextureSupport() const -{ - return true; -} - int Renderer11::getMajorShaderModel() const { switch (mFeatureLevel) @@ -2122,8 +1910,7 @@ int Renderer11::getMajorShaderModel() const 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 + case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MAJOR_VERSION; // 4 default: UNREACHABLE(); return 0; } } @@ -2152,100 +1939,12 @@ int Renderer11::getMaxSwapInterval() const return 4; } -int Renderer11::getMaxSupportedSamples() const -{ - return mMaxSupportedSamples; -} - -GLsizei Renderer11::getMaxSupportedFormatSamples(GLenum internalFormat) const -{ - DXGI_FORMAT format = gl_d3d11::GetRenderableFormat(internalFormat); - MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); - return (iter != mMultisampleSupportMap.end()) ? iter->second.maxSupportedSamples : 0; -} - -GLsizei Renderer11::getNumSampleCounts(GLenum internalFormat) const -{ - unsigned int numCounts = 0; - - // D3D11 supports multisampling for signed and unsigned format, but ES 3.0 does not - GLenum componentType = gl::GetComponentType(internalFormat); - if (componentType != GL_INT && componentType != GL_UNSIGNED_INT) - { - DXGI_FORMAT format = gl_d3d11::GetRenderableFormat(internalFormat); - MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); - - if (iter != mMultisampleSupportMap.end()) - { - const MultisampleSupportInfo& info = iter->second; - for (int i = 0; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++) - { - if (info.qualityLevels[i] > 0) - { - numCounts++; - } - } - } - } - - return numCounts; -} - -void Renderer11::getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const -{ - // D3D11 supports multisampling for signed and unsigned format, but ES 3.0 does not - GLenum componentType = gl::GetComponentType(internalFormat); - if (componentType == GL_INT || componentType == GL_UNSIGNED_INT) - { - return; - } - - DXGI_FORMAT format = gl_d3d11::GetRenderableFormat(internalFormat); - MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); - - if (iter != mMultisampleSupportMap.end()) - { - const MultisampleSupportInfo& info = iter->second; - int bufPos = 0; - for (int i = D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT - 1; i >= 0 && bufPos < bufSize; i--) - { - if (info.qualityLevels[i] > 0) - { - params[bufPos++] = i + 1; - } - } - } -} - -int Renderer11::getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const -{ - if (requested == 0) - { - return 0; - } - - MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); - if (iter != mMultisampleSupportMap.end()) - { - const MultisampleSupportInfo& info = iter->second; - for (unsigned int i = requested - 1; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++) - { - if (info.qualityLevels[i] > 0) - { - return i + 1; - } - } - } - - return -1; -} - -bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) +bool Renderer11::copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source) { if (source && dest) { - TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source->getStorageInstance()); - TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest->getStorageInstance()); + TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source); + TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest); mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); @@ -2257,12 +1956,12 @@ bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStor return false; } -bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) +bool Renderer11::copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source) { if (source && dest) { - TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source->getStorageInstance()); - TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest->getStorageInstance()); + TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source); + TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest); mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); @@ -2274,12 +1973,12 @@ bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureSt return false; } -bool Renderer11::copyToRenderTarget(TextureStorageInterface3D *dest, TextureStorageInterface3D *source) +bool Renderer11::copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source) { if (source && dest) { - TextureStorage11_3D *source11 = TextureStorage11_3D::makeTextureStorage11_3D(source->getStorageInstance()); - TextureStorage11_3D *dest11 = TextureStorage11_3D::makeTextureStorage11_3D(dest->getStorageInstance()); + TextureStorage11_3D *source11 = TextureStorage11_3D::makeTextureStorage11_3D(source); + TextureStorage11_3D *dest11 = TextureStorage11_3D::makeTextureStorage11_3D(dest); mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); @@ -2291,12 +1990,12 @@ bool Renderer11::copyToRenderTarget(TextureStorageInterface3D *dest, TextureStor return false; } -bool Renderer11::copyToRenderTarget(TextureStorageInterface2DArray *dest, TextureStorageInterface2DArray *source) +bool Renderer11::copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source) { if (source && dest) { - TextureStorage11_2DArray *source11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(source->getStorageInstance()); - TextureStorage11_2DArray *dest11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(dest->getStorageInstance()); + TextureStorage11_2DArray *source11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(source); + TextureStorage11_2DArray *dest11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(dest); mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); @@ -2308,8 +2007,8 @@ bool Renderer11::copyToRenderTarget(TextureStorageInterface2DArray *dest, Textur return false; } -bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) +bool Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) { gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); if (!colorbuffer) @@ -2318,7 +2017,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so return gl::error(GL_OUT_OF_MEMORY, false); } - RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer); if (!sourceRenderTarget) { ERR("Failed to retrieve the render target from the frame buffer."); @@ -2332,14 +2031,15 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so return gl::error(GL_OUT_OF_MEMORY, false); } - TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); + TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage); if (!storage11) { ERR("Failed to retrieve the texture storage from the destination."); return gl::error(GL_OUT_OF_MEMORY, false); } - RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(level)); + gl::ImageIndex index = gl::ImageIndex::Make2D(level); + RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index)); if (!destRenderTarget) { ERR("Failed to retrieve the render target from the destination storage."); @@ -2369,8 +2069,8 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so return ret; } -bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) +bool 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(); if (!colorbuffer) @@ -2379,7 +2079,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so return gl::error(GL_OUT_OF_MEMORY, false); } - RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer); if (!sourceRenderTarget) { ERR("Failed to retrieve the render target from the frame buffer."); @@ -2393,14 +2093,15 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so return gl::error(GL_OUT_OF_MEMORY, false); } - TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); + TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage); if (!storage11) { ERR("Failed to retrieve the texture storage from the destination."); return gl::error(GL_OUT_OF_MEMORY, false); } - RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTargetFace(target, level)); + gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level); + RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index)); if (!destRenderTarget) { ERR("Failed to retrieve the render target from the destination storage."); @@ -2430,8 +2131,8 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so return ret; } -bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface3D *storage, GLint level) +bool 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(); if (!colorbuffer) @@ -2440,7 +2141,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so return gl::error(GL_OUT_OF_MEMORY, false); } - RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer); if (!sourceRenderTarget) { ERR("Failed to retrieve the render target from the frame buffer."); @@ -2454,14 +2155,15 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so return gl::error(GL_OUT_OF_MEMORY, false); } - TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage->getStorageInstance()); + TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage); if (!storage11) { ERR("Failed to retrieve the texture storage from the destination."); return gl::error(GL_OUT_OF_MEMORY, false); } - RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTargetLayer(level, zOffset)); + gl::ImageIndex index = gl::ImageIndex::Make3D(level, zOffset); + RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index)); if (!destRenderTarget) { ERR("Failed to retrieve the render target from the destination storage."); @@ -2491,8 +2193,8 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so return ret; } -bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level) +bool 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(); if (!colorbuffer) @@ -2501,7 +2203,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so return gl::error(GL_OUT_OF_MEMORY, false); } - RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + RenderTarget11 *sourceRenderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer); if (!sourceRenderTarget) { ERR("Failed to retrieve the render target from the frame buffer."); @@ -2515,7 +2217,7 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so return gl::error(GL_OUT_OF_MEMORY, false); } - TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage->getStorageInstance()); + TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage); if (!storage11) { SafeRelease(source); @@ -2523,7 +2225,8 @@ bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &so return gl::error(GL_OUT_OF_MEMORY, false); } - RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTargetLayer(level, zOffset)); + gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, zOffset); + RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(index)); if (!destRenderTarget) { SafeRelease(source); @@ -2604,6 +2307,21 @@ RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum forma return renderTarget; } +ShaderImpl *Renderer11::createShader(GLenum type) +{ + return new ShaderD3D(type, this); +} + +ProgramImpl *Renderer11::createProgram() +{ + return new ProgramD3D(this); +} + +void Renderer11::releaseShaderCompiler() +{ + ShaderD3D::releaseCompiler(); +} + ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type, const std::vector &transformFeedbackVaryings, bool separatedOutputBuffers) @@ -2818,30 +2536,39 @@ FenceImpl *Renderer11::createFence() return new Fence11(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 (gl::GetColorEncoding(internalFormat) == GL_SRGB) + if (internalFormatInfo.colorEncoding == GL_SRGB) { return false; } // We cannot support direct copies to non-color-renderable formats - if (gl_d3d11::GetRTVFormat(internalFormat) != DXGI_FORMAT_UNKNOWN) + if (d3d11FormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN) { return false; } // We skip all 3-channel formats since sometimes format support is missing - if (gl::GetComponentCount(internalFormat) == 3) + if (internalFormatInfo.componentCount == 3) { return false; } // We don't support formats which we can't represent without conversion - if (getNativeTextureFormat(internalFormat) != internalFormat) + if (dxgiFormatInfo.internalFormat != internalFormat) { return false; } @@ -2860,7 +2587,7 @@ bool Renderer11::getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, { ASSERT(colorbuffer != NULL); - RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + RenderTarget11 *renderTarget = d3d11::GetAttachmentRenderTarget(colorbuffer); if (renderTarget) { *subresourceIndex = renderTarget->getSubresourceIndex(); @@ -2905,7 +2632,7 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read return gl::error(GL_OUT_OF_MEMORY, false); } - RenderTarget *readRenderTarget = readBuffer->getRenderTarget(); + RenderTarget *readRenderTarget = GetAttachmentRenderTarget(readBuffer); for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { @@ -2919,7 +2646,7 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read return gl::error(GL_OUT_OF_MEMORY, false); } - RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget(); + RenderTarget *drawRenderTarget = GetAttachmentRenderTarget(drawBuffer); if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, blitRenderTarget, false, false)) @@ -2947,8 +2674,9 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read return gl::error(GL_OUT_OF_MEMORY, false); } - RenderTarget *readRenderTarget = readBuffer->getDepthStencil(); - RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil(); + RenderTarget *readRenderTarget = GetAttachmentRenderTarget(readBuffer); + RenderTarget *drawRenderTarget = GetAttachmentRenderTarget(drawBuffer); + ASSERT(readRenderTarget && drawRenderTarget); if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, false, blitDepth, blitStencil)) @@ -2962,8 +2690,8 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read return true; } -void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels) +gl::Error Renderer11::readPixels(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; @@ -2978,19 +2706,33 @@ void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsi area.width = width; area.height = height; - if (pack.pixelBuffer.get() != NULL) + gl::Buffer *packBuffer = pack.pixelBuffer.get(); + if (packBuffer != NULL) { - rx::Buffer11 *packBufferStorage = Buffer11::makeBuffer11(pack.pixelBuffer.get()->getImplementation()); + rx::Buffer11 *packBufferStorage = Buffer11::makeBuffer11(packBuffer->getImplementation()); PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast(pixels)); - packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams); + + gl::Error error = packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams); + if (error.isError()) + { + return error; + } + + packBuffer->getIndexRangeCache()->clear(); } else { - readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels); + gl::Error error = readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels); + if (error.isError()) + { + return error; + } } SafeRelease(colorBufferTexture); } + + return gl::Error(GL_NO_ERROR); } Image *Renderer11::createImage() @@ -3031,28 +2773,23 @@ TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat, b return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth, levels); } -Texture2DImpl *Renderer11::createTexture2D() +TextureImpl *Renderer11::createTexture(GLenum target) { - return new TextureD3D_2D(this); -} - -TextureCubeImpl *Renderer11::createTextureCube() -{ - return new TextureD3D_Cube(this); -} - -Texture3DImpl *Renderer11::createTexture3D() -{ - return new TextureD3D_3D(this); -} + 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(); + } -Texture2DArrayImpl *Renderer11::createTexture2DArray() -{ - return new TextureD3D_2DArray(this); + return NULL; } -void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void *pixels) +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); @@ -3077,7 +2814,7 @@ void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResou if (safeArea.width == 0 || safeArea.height == 0) { // no work to do - return; + return gl::Error(GL_NO_ERROR); } D3D11_TEXTURE2D_DESC stagingDesc; @@ -3097,8 +2834,7 @@ void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResou HRESULT result = mDevice->CreateTexture2D(&stagingDesc, NULL, &stagingTex); if (FAILED(result)) { - ERR("Failed to create staging texture for readPixels, HRESULT: 0x%X.", result); - return; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal staging texture for ReadPixels, HRESULT: 0x%X.", result); } ID3D11Texture2D* srcTex = NULL; @@ -3120,9 +2856,8 @@ void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResou result = mDevice->CreateTexture2D(&resolveDesc, NULL, &srcTex); if (FAILED(result)) { - ERR("Failed to create resolve texture for readPixels, HRESULT: 0x%X.", result); SafeRelease(stagingTex); - return; + 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); @@ -3150,9 +2885,11 @@ void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResou packPixels(stagingTex, packParams, pixels); SafeRelease(stagingTex); + + return gl::Error(GL_NO_ERROR); } -void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, void *pixelsOut) +void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, uint8_t *pixelsOut) { D3D11_TEXTURE2D_DESC textureDesc; readTexture->GetDesc(&textureDesc); @@ -3162,39 +2899,37 @@ void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams UNUSED_ASSERTION_VARIABLE(hr); ASSERT(SUCCEEDED(hr)); - unsigned char *source; + uint8_t *source; int inputPitch; if (params.pack.reverseRowOrder) { - source = static_cast(mapping.pData) + mapping.RowPitch * (params.area.height - 1); + source = static_cast(mapping.pData) + mapping.RowPitch * (params.area.height - 1); inputPitch = -static_cast(mapping.RowPitch); } else { - source = static_cast(mapping.pData); + source = static_cast(mapping.pData); inputPitch = static_cast(mapping.RowPitch); } - GLenum sourceInternalFormat = d3d11_gl::GetInternalFormat(textureDesc.Format); - GLenum sourceFormat = gl::GetFormat(sourceInternalFormat); - GLenum sourceType = gl::GetType(sourceInternalFormat); - - GLuint sourcePixelSize = gl::GetPixelBytes(sourceInternalFormat); - - if (sourceFormat == params.format && sourceType == params.type) + 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) { - unsigned char *dest = static_cast(pixelsOut) + params.offset; + 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 * sourcePixelSize); + memcpy(dest + y * params.outputPitch, source + y * inputPitch, params.area.width * sourceFormatInfo.pixelBytes); } } else { - GLenum destInternalFormat = gl::GetSizedInternalFormat(params.format, params.type); - GLuint destPixelSize = gl::GetPixelBytes(destInternalFormat); + 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); - ColorCopyFunction fastCopyFunc = d3d11::GetFastCopyFunction(textureDesc.Format, params.format, params.type); if (fastCopyFunc) { // Fast copy is possible through some special function @@ -3202,8 +2937,8 @@ void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams { for (int x = 0; x < params.area.width; x++) { - void *dest = static_cast(pixelsOut) + params.offset + y * params.outputPitch + x * destPixelSize; - void *src = static_cast(source) + y * inputPitch + x * sourcePixelSize; + 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); } @@ -3211,10 +2946,7 @@ void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams } else { - ColorReadFunction readFunc = d3d11::GetColorReadFunction(textureDesc.Format); - ColorWriteFunction writeFunc = gl::GetColorWriteFunction(params.format, params.type); - - unsigned char temp[16]; // Maximum size of any Color type used. + 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)); @@ -3223,13 +2955,13 @@ void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams { for (int x = 0; x < params.area.width; x++) { - void *dest = static_cast(pixelsOut) + params.offset + y * params.outputPitch + x * destPixelSize; - void *src = static_cast(source) + y * inputPitch + x * sourcePixelSize; + 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. - readFunc(src, temp); - writeFunc(temp, dest); + sourceDXGIFormatInfo.colorReadFunction(src, temp); + destFormatTypeInfo.colorWriteFunction(temp, dest); } } } @@ -3328,9 +3060,8 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width || drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height; - bool hasDepth = gl::GetDepthBits(drawRenderTarget11->getActualFormat()) > 0; - bool hasStencil = gl::GetStencilBits(drawRenderTarget11->getActualFormat()) > 0; - bool partialDSBlit = (hasDepth && depthBlit) != (hasStencil && stencilBlit); + const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getActualFormat()); + bool partialDSBlit = (actualFormatInfo.depthBits > 0 && depthBlit) != (actualFormatInfo.stencilBits > 0 && stencilBlit); if (readRenderTarget11->getActualFormat() == drawRenderTarget->getActualFormat() && !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit && @@ -3404,7 +3135,7 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R } else { - GLenum format = gl::GetFormat(drawRenderTarget->getInternalFormat()); + GLenum format = gl::GetInternalFormatInfo(drawRenderTarget->getInternalFormat()).format; result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize, scissor, format, filter); } @@ -3457,7 +3188,9 @@ ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, void Renderer11::invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel) { ASSERT(attachment->isTexture()); - TextureStorage *texStorage = attachment->getTextureStorage(); + gl::Texture *texture = attachment->getTexture(); + + TextureStorage *texStorage = texture->getNativeTexture(); if (texStorage) { TextureStorage11 *texStorage11 = TextureStorage11::makeTextureStorage11(texStorage); @@ -3515,46 +3248,14 @@ bool Renderer11::getLUID(LUID *adapterLuid) const return true; } -GLenum Renderer11::getNativeTextureFormat(GLenum internalFormat) const -{ - return d3d11_gl::GetInternalFormat(gl_d3d11::GetTexFormat(internalFormat)); -} - rx::VertexConversionType Renderer11::getVertexConversionType(const gl::VertexFormat &vertexFormat) const { - return gl_d3d11::GetVertexConversionType(vertexFormat); + return d3d11::GetVertexFormatInfo(vertexFormat).conversionType; } GLenum Renderer11::getVertexComponentType(const gl::VertexFormat &vertexFormat) const { - return d3d11::GetComponentType(gl_d3d11::GetNativeVertexFormat(vertexFormat)); -} - -Renderer11::MultisampleSupportInfo Renderer11::getMultisampleSupportInfo(DXGI_FORMAT format) -{ - MultisampleSupportInfo supportInfo = { 0 }; - - UINT formatSupport; - HRESULT result; - - result = mDevice->CheckFormatSupport(format, &formatSupport); - if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)) - { - for (unsigned int i = 1; i <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++) - { - result = mDevice->CheckMultisampleQualityLevels(format, i, &supportInfo.qualityLevels[i - 1]); - if (SUCCEEDED(result) && supportInfo.qualityLevels[i - 1] > 0) - { - supportInfo.maxSupportedSamples = std::max(supportInfo.maxSupportedSamples, i); - } - else - { - supportInfo.qualityLevels[i - 1] = 0; - } - } - } - - return supportInfo; + return d3d11::GetDXGIFormatInfo(d3d11::GetVertexFormatInfo(vertexFormat).nativeFormat).componentType; } void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const 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 b54f75d859..2a53fa1672 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h @@ -59,37 +59,37 @@ class Renderer11 : public Renderer virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); - virtual void generateSwizzle(gl::Texture *texture); - virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); - virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); + virtual gl::Error generateSwizzle(gl::Texture *texture); + virtual gl::Error setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); + virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture); - virtual bool setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]); + virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]); - virtual void setRasterizerState(const gl::RasterizerState &rasterState); - virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask); - virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW); + virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState); + virtual gl::Error setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, + unsigned int sampleMask); + virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW); virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); - virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, bool ignoreViewport); virtual bool applyPrimitiveType(GLenum mode, GLsizei count); - virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); - virtual void applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, bool transformFeedbackActive); - virtual void applyUniforms(const gl::ProgramBinary &programBinary); - virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], - GLint first, GLsizei count, GLsizei instances); - virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); + virtual gl::Error applyRenderTarget(gl::Framebuffer *frameBuffer); + virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive); + virtual gl::Error applyUniforms(const gl::ProgramBinary &programBinary); + virtual gl::Error applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], + 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(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]); - virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive); - virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); + 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); - virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); + virtual gl::Error clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); virtual void markAllStateDirty(); @@ -103,63 +103,48 @@ class Renderer11 : public Renderer virtual std::string getRendererDescription() const; virtual GUID getAdapterIdentifier() const; - virtual unsigned int getMaxVertexTextureImageUnits() const; - virtual unsigned int getMaxCombinedTextureImageUnits() const; virtual unsigned int getReservedVertexUniformVectors() const; virtual unsigned int getReservedFragmentUniformVectors() const; - virtual unsigned int getMaxVertexUniformVectors() const; - virtual unsigned int getMaxFragmentUniformVectors() const; - virtual unsigned int getMaxVaryingVectors() const; - virtual unsigned int getMaxVertexShaderUniformBuffers() const; - virtual unsigned int getMaxFragmentShaderUniformBuffers() const; virtual unsigned int getReservedVertexUniformBuffers() const; virtual unsigned int getReservedFragmentUniformBuffers() const; - unsigned int getReservedVaryings() const; - virtual unsigned int getMaxTransformFeedbackBuffers() const; - virtual unsigned int getMaxTransformFeedbackSeparateComponents() const; - virtual unsigned int getMaxTransformFeedbackInterleavedComponents() const; - virtual unsigned int getMaxUniformBufferSize() const; virtual bool getShareHandleSupport() const; virtual bool getPostSubBufferSupport() const; - virtual int getMaxRecommendedElementsIndices() const; - virtual int getMaxRecommendedElementsVertices() const; - virtual bool getSRGBTextureSupport() const; virtual int getMajorShaderModel() const; virtual int getMinSwapInterval() const; virtual int getMaxSwapInterval() const; - virtual GLsizei getMaxSupportedSamples() const; - virtual GLsizei getMaxSupportedFormatSamples(GLenum internalFormat) const; - virtual GLsizei getNumSampleCounts(GLenum internalFormat) const; - virtual void getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const; - int getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const; - // Pixel operations - virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source); - virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source); - virtual bool copyToRenderTarget(TextureStorageInterface3D *dest, TextureStorageInterface3D *source); - virtual bool copyToRenderTarget(TextureStorageInterface2DArray *dest, TextureStorageInterface2DArray *source); - - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface3D *storage, GLint level); - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level); + virtual bool copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source); + virtual bool copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source); + virtual bool copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source); + virtual bool copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source); + + virtual bool copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level); + virtual bool copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level); + virtual bool copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); + virtual bool copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter); - virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels); + + virtual gl::Error readPixels(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 RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples); + // Shader creation + virtual ShaderImpl *createShader(GLenum type); + virtual ProgramImpl *createProgram(); + // Shader operations + virtual void releaseShaderCompiler(); virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, const std::vector &transformFeedbackVaryings, bool separatedOutputBuffers); @@ -178,10 +163,7 @@ class Renderer11 : public Renderer virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); // Texture creation - virtual Texture2DImpl *createTexture2D(); - virtual TextureCubeImpl *createTextureCube(); - virtual Texture3DImpl *createTexture3D(); - virtual Texture2DArrayImpl *createTexture2DArray(); + virtual TextureImpl *createTexture(GLenum target); // Buffer creation virtual BufferImpl *createBuffer(); @@ -195,6 +177,9 @@ class Renderer11 : public Renderer virtual QueryImpl *createQuery(GLenum type); virtual FenceImpl *createFence(); + // Transform Feedback creation + virtual TransformFeedbackImpl* createTransformFeedback(); + // D3D11-renderer specific methods ID3D11Device *getDevice() { return mDevice; } ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; @@ -211,10 +196,9 @@ class Renderer11 : public Renderer bool getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource); void unapplyRenderTargets(); void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView); - void packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, void *pixelsOut); + void packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, uint8_t *pixelsOut); virtual bool getLUID(LUID *adapterLuid) const; - virtual GLenum getNativeTextureFormat(GLenum internalFormat) const; virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const; @@ -223,11 +207,11 @@ class Renderer11 : public Renderer virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const; - void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); - void drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances); + 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); - void readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void *pixels); + 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); bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, @@ -253,19 +237,6 @@ class Renderer11 : public Renderer RenderStateCache mStateCache; - // Multisample format support - struct MultisampleSupportInfo - { - unsigned int qualityLevels[D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT]; - unsigned int maxSupportedSamples; - }; - MultisampleSupportInfo getMultisampleSupportInfo(DXGI_FORMAT format); - - typedef std::unordered_map MultisampleSupportMap; - MultisampleSupportMap mMultisampleSupportMap; - - unsigned int mMaxSupportedSamples; - // current render target states unsigned int mAppliedRenderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; unsigned int mAppliedDepthbufferSerial; @@ -275,15 +246,15 @@ class Renderer11 : public Renderer rx::RenderTarget::Desc mRenderTargetDesc; // Currently applied sampler states - bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + std::vector mForceSetVertexSamplerStates; + std::vector mCurVertexSamplerStates; - bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; - gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; + std::vector mForceSetPixelSamplerStates; + std::vector mCurPixelSamplerStates; // Currently applied textures - ID3D11ShaderResourceView *mCurVertexSRVs[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - ID3D11ShaderResourceView *mCurPixelSRVs[gl::MAX_TEXTURE_IMAGE_UNITS]; + std::vector mCurVertexSRVs; + std::vector mCurPixelSRVs; // Currently applied blend state bool mForceSetBlendState; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp index 5a7c987494..52f34887fb 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -9,7 +8,6 @@ // executable implementation details. #include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" - #include "libGLESv2/renderer/d3d/d3d11/Renderer11.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 0341df10f9..4b29be055d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -7,12 +6,13 @@ // SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. -#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" - #include "common/platform.h" +#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" @@ -94,8 +94,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei ASSERT(backbufferWidth >= 1); ASSERT(backbufferHeight >= 1); -#if !defined(ANGLE_PLATFORM_WINRT) // Preserve the render target content +#if !defined(ANGLE_PLATFORM_WINRT) ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; if (previousOffscreenTexture) { @@ -107,6 +107,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei 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) @@ -135,11 +137,11 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; mOffscreenTexture->GetDesc(&offscreenTextureDesc); - if (offscreenTextureDesc.Width != (UINT)backbufferWidth - || offscreenTextureDesc.Height != (UINT)backbufferHeight - || offscreenTextureDesc.Format != gl_d3d11::GetTexFormat(mBackBufferFormat) - || offscreenTextureDesc.MipLevels != 1 - || offscreenTextureDesc.ArraySize != 1) + 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(); @@ -153,7 +155,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; offscreenTextureDesc.Width = backbufferWidth; offscreenTextureDesc.Height = backbufferHeight; - offscreenTextureDesc.Format = gl_d3d11::GetTexFormat(mBackBufferFormat); + offscreenTextureDesc.Format = backbufferFormatInfo.texFormat; offscreenTextureDesc.MipLevels = 1; offscreenTextureDesc.ArraySize = 1; offscreenTextureDesc.SampleDesc.Count = 1; @@ -209,7 +211,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc; - offscreenRTVDesc.Format = gl_d3d11::GetRTVFormat(mBackBufferFormat); + offscreenRTVDesc.Format = backbufferFormatInfo.rtvFormat; offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; offscreenRTVDesc.Texture2D.MipSlice = 0; @@ -218,7 +220,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei d3d11::SetDebugName(mOffscreenRTView, "Offscreen back buffer render target"); D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc; - offscreenSRVDesc.Format = gl_d3d11::GetSRVFormat(mBackBufferFormat); + offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat; offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; offscreenSRVDesc.Texture2D.MostDetailedMip = 0; offscreenSRVDesc.Texture2D.MipLevels = -1; @@ -227,12 +229,14 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei 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 = backbufferWidth; depthStencilTextureDesc.Height = backbufferHeight; - depthStencilTextureDesc.Format = gl_d3d11::GetTexFormat(mDepthBufferFormat); + depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat; depthStencilTextureDesc.MipLevels = 1; depthStencilTextureDesc.ArraySize = 1; depthStencilTextureDesc.SampleDesc.Count = 1; @@ -260,7 +264,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei d3d11::SetDebugName(mDepthStencilTexture, "Offscreen depth stencil texture"); D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilDesc; - depthStencilDesc.Format = gl_d3d11::GetDSVFormat(mDepthBufferFormat); + depthStencilDesc.Format = depthBufferFormatInfo.dsvFormat; depthStencilDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; depthStencilDesc.Flags = 0; depthStencilDesc.Texture2D.MipSlice = 0; @@ -270,7 +274,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei d3d11::SetDebugName(mDepthStencilDSView, "Offscreen depth stencil view"); D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc; - depthStencilSRVDesc.Format = gl_d3d11::GetSRVFormat(mDepthBufferFormat); + depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat; depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; depthStencilSRVDesc.Texture2D.MostDetailedMip = 0; depthStencilSRVDesc.Texture2D.MipLevels = -1; @@ -343,8 +347,8 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) #else const int bufferCount = 2; #endif - DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::GetTexFormat(mBackBufferFormat); - result = mSwapChain->ResizeBuffers(bufferCount, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0); + const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat); + result = mSwapChain->ResizeBuffers(bufferCount, backbufferWidth, backbufferHeight, backbufferFormatInfo.texFormat, 0); if (FAILED(result)) { @@ -361,6 +365,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) } } #endif + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); ASSERT(SUCCEEDED(result)); if (SUCCEEDED(result)) @@ -409,14 +414,17 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap if (mWindow) { + const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat); + IDXGIFactory *factory = mRenderer->getDxgiFactory(); + #if !defined(ANGLE_PLATFORM_WINRT) DXGI_SWAP_CHAIN_DESC swapChainDesc = {0}; swapChainDesc.BufferDesc.Width = backbufferWidth; swapChainDesc.BufferDesc.Height = backbufferHeight; swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; - swapChainDesc.BufferDesc.Format = gl_d3d11::GetTexFormat(mBackBufferFormat); + swapChainDesc.BufferDesc.Format = backbufferFormatInfo.texFormat; swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; swapChainDesc.SampleDesc.Count = 1; @@ -437,7 +445,7 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; swapChainDesc.Width = 0; swapChainDesc.Height = 0; - swapChainDesc.Format = gl_d3d11::GetTexFormat(mBackBufferFormat); + swapChainDesc.Format = backbufferFormatInfo.texFormat; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; @@ -460,7 +468,6 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap mViewportWidth = swapChainDesc.Width; mViewportHeight = swapChainDesc.Height; #endif - if (FAILED(result)) { ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); @@ -530,7 +537,7 @@ void SwapChain11::initPassThroughResources() samplerDesc.BorderColor[2] = 0.0f; samplerDesc.BorderColor[3] = 0.0f; samplerDesc.MinLOD = 0; - samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + samplerDesc.MaxLOD = FLT_MAX; result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler); ASSERT(SUCCEEDED(result)); @@ -636,7 +643,7 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EG // Draw deviceContext->Draw(4, 0); -#if ANGLE_FORCE_VSYNC_OFF +#ifdef ANGLE_FORCE_VSYNC_OFF result = mSwapChain->Present(0, 0); #else result = mSwapChain->Present(mSwapInterval, 0); 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 00b81b7c92..91e7147da6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -9,17 +8,18 @@ // classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. #include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" - -#include "libGLESv2/renderer/d3d/TextureD3D.h" #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/TextureD3D.h" +#include "libGLESv2/main.h" +#include "libGLESv2/ImageIndex.h" #include "common/utilities.h" -#include "libGLESv2/main.h" namespace rx { @@ -126,15 +126,16 @@ DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, bool renderTa { UINT bindFlags = 0; - if (gl_d3d11::GetSRVFormat(internalFormat) != DXGI_FORMAT_UNKNOWN) + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat); + if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN) { bindFlags |= D3D11_BIND_SHADER_RESOURCE; } - if (gl_d3d11::GetDSVFormat(internalFormat) != DXGI_FORMAT_UNKNOWN) + if (formatInfo.dsvFormat != DXGI_FORMAT_UNKNOWN) { bindFlags |= D3D11_BIND_DEPTH_STENCIL; } - if (gl_d3d11::GetRTVFormat(internalFormat) != DXGI_FORMAT_UNKNOWN && renderTarget) + if (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN && renderTarget) { bindFlags |= D3D11_BIND_RENDER_TARGET; } @@ -195,7 +196,7 @@ UINT TextureStorage11::getSubresourceIndex(int mipLevel, int layerTarget) const ID3D11ShaderResourceView *TextureStorage11::getSRV(const gl::SamplerState &samplerState) { bool swizzleRequired = samplerState.swizzleRequired(); - bool mipmapping = IsMipmapFiltered(samplerState); + 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) @@ -239,7 +240,7 @@ ID3D11ShaderResourceView *TextureStorage11::getSRVLevel(int mipLevel) } } -void TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) +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++) @@ -255,16 +256,17 @@ void TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, Blit11 *blitter = mRenderer->getBlitter(); - if (blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha)) + gl::Error error = blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); + if (error.isError()) { - mSwizzleCache[level] = swizzleTarget; - } - else - { - ERR("Failed to swizzle texture."); + return error; } + + mSwizzleCache[level] = swizzleTarget; } } + + return gl::Error(GL_NO_ERROR); } void TextureStorage11::invalidateSwizzleCacheLevel(int mipLevel) @@ -308,7 +310,8 @@ bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsign ASSERT(dstTexture); - if (!fullCopy && (d3d11::GetDepthBits(mTextureFormat) > 0 || d3d11::GetStencilBits(mTextureFormat) > 0)) + 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(); @@ -319,11 +322,13 @@ bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsign } else { + const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat); + D3D11_BOX srcBox; srcBox.left = copyArea.x; srcBox.top = copyArea.y; - srcBox.right = copyArea.x + roundUp((unsigned int)width, d3d11::GetBlockWidth(mTextureFormat)); - srcBox.bottom = copyArea.y + roundUp((unsigned int)height, d3d11::GetBlockHeight(mTextureFormat)); + srcBox.right = copyArea.x + roundUp((unsigned int)width, dxgiFormatInfo.blockWidth); + srcBox.bottom = copyArea.y + roundUp((unsigned int)height, dxgiFormatInfo.blockHeight); srcBox.front = copyArea.z; srcBox.back = copyArea.z + copyArea.depth; @@ -338,6 +343,27 @@ bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsign return false; } +bool TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, + int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth) +{ + if (dstTexture) + { + ID3D11Resource *srcTexture = getResource(); + unsigned int srcSubresource = getSubresourceIndex(level + mTopLevel, layerTarget); + + ASSERT(srcTexture); + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + context->CopySubresourceRegion(dstTexture, dstSubresource, xoffset, yoffset, zoffset, + srcTexture, srcSubresource, NULL); + return true; + } + + return false; +} + void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest) { if (source && dest) @@ -356,7 +382,7 @@ void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget1 Blit11 *blitter = mRenderer->getBlitter(); blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL, - gl::GetFormat(source->getInternalFormat()), GL_LINEAR); + gl::GetInternalFormatInfo(source->getInternalFormat()).format, GL_LINEAR); } } } @@ -371,14 +397,15 @@ void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGree } TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain) - : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE) + : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE), + mTexture(swapchain->getOffscreenTexture()), + mSwizzleTexture(NULL) { - mTexture = swapchain->getOffscreenTexture(); mTexture->AddRef(); - mSwizzleTexture = NULL; for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { + mAssociatedImages[i] = NULL; mRenderTarget[i] = NULL; mSwizzleRenderTargets[i] = NULL; } @@ -401,33 +428,37 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapch offscreenRTV->GetDesc(&rtvDesc); mRenderTargetFormat = rtvDesc.Format; - GLenum internalFormat = d3d11_gl::GetInternalFormat(mTextureFormat); - mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalFormat); - mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalFormat); - mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalFormat); + 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(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) - : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)), + mTexture(NULL), + mSwizzleTexture(NULL) { - 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; } - mTextureFormat = gl_d3d11::GetTexFormat(internalformat); - mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat); - mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat); - mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat); - mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat); - mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat); - mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(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; // 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 @@ -441,7 +472,7 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalform D3D11_TEXTURE2D_DESC desc; desc.Width = width; // Compressed texture size constraints? desc.Height = height; - desc.MipLevels = mRenderer->isLevel9() ? 1 : ((levels > 0) ? (mTopLevel + levels) : 0); + desc.MipLevels = desc.MipLevels = mRenderer->isLevel9() ? 1 : ((levels > 0) ? (mTopLevel + levels) : 0); desc.ArraySize = 1; desc.Format = mTextureFormat; desc.SampleDesc.Count = 1; @@ -474,10 +505,27 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalform 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. + mAssociatedImages[i]->recoverFromAssociatedStorage(); + } + } + } + SafeRelease(mTexture); SafeRelease(mSwizzleTexture); @@ -494,13 +542,80 @@ TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage return static_cast(storage); } +void TextureStorage11_2D::associateImage(Image11* image, int level, int layerTarget) +{ + 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(int level, int layerTarget, Image11* expectedImage) +{ + 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(int level, int layerTarget, Image11* expectedImage) +{ + 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. +void TextureStorage11_2D::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) +{ + 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. + mAssociatedImages[level]->recoverFromAssociatedStorage(); + } + } + } +} + ID3D11Resource *TextureStorage11_2D::getResource() const { return mTexture; } -RenderTarget *TextureStorage11_2D::getRenderTarget(int level) +RenderTarget *TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index) { + ASSERT(!index.hasLayer()); + + int level = index.mipIndex; + if (level >= 0 && level < getLevelCount()) { if (!mRenderTarget[level]) @@ -595,14 +710,22 @@ ID3D11ShaderResourceView *TextureStorage11_2D::createSRV(int baseLevel, int mipL return SRV; } -void TextureStorage11_2D::generateMipmap(int level) +void TextureStorage11_2D::generateMipmaps() { - invalidateSwizzleCacheLevel(level); + // Base level must already be defined + + for (int level = 1; level < getLevelCount(); level++) + { + invalidateSwizzleCacheLevel(level); + + gl::ImageIndex srcIndex = gl::ImageIndex::Make2D(level - 1); + gl::ImageIndex destIndex = gl::ImageIndex::Make2D(level); - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex)); - generateMipmapLayer(source, dest); + generateMipmapLayer(source, dest); + } } ID3D11Resource *TextureStorage11_2D::getSwizzleTexture() @@ -671,11 +794,6 @@ ID3D11RenderTargetView *TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel } } -unsigned int TextureStorage11_2D::getTextureLevelDepth(int mipLevel) const -{ - return 1; -} - TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels) : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) { @@ -687,17 +805,19 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internal mSwizzleRenderTargets[level] = NULL; for (unsigned int face = 0; face < 6; face++) { + mAssociatedImages[face][level] = NULL; mRenderTarget[face][level] = NULL; } } - mTextureFormat = gl_d3d11::GetTexFormat(internalformat); - mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat); - mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat); - mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat); - mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat); - mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat); - mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(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; // if the size is not positive this should be treated as an incomplete texture // we handle that here by skipping the d3d texture creation @@ -739,10 +859,31 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, GLenum internal mTextureDepth = 1; } } + + initializeSerials(getLevelCount() * 6, 6); } + TextureStorage11_Cube::~TextureStorage11_Cube() { + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + for (unsigned int face = 0; face < 6; 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); @@ -762,16 +903,96 @@ TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureS return static_cast(storage); } +void TextureStorage11_Cube::associateImage(Image11* image, int level, int layerTarget) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < 6); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + if (0 <= layerTarget && layerTarget < 6) + { + mAssociatedImages[layerTarget][level] = image; + } + } +} + +bool TextureStorage11_Cube::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) +{ + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + if (0 <= layerTarget && layerTarget < 6) + { + // 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(int level, int layerTarget, Image11* expectedImage) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < 6); + + if (0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + { + if (0 <= layerTarget && layerTarget < 6) + { + 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. +void TextureStorage11_Cube::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) +{ + ASSERT(0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(0 <= layerTarget && layerTarget < 6); + + if ((0 <= level && level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)) + { + if (0 <= layerTarget && layerTarget < 6) + { + // 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. + mAssociatedImages[layerTarget][level]->recoverFromAssociatedStorage(); + } + } + } + } +} + ID3D11Resource *TextureStorage11_Cube::getResource() const { return mTexture; } -RenderTarget *TextureStorage11_Cube::getRenderTargetFace(GLenum faceTarget, int level) +RenderTarget *TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index) { + int faceIndex = index.layerIndex; + int level = index.mipIndex; + if (level >= 0 && level < getLevelCount()) { - int faceIndex = TextureD3D_Cube::targetToIndex(faceTarget); if (!mRenderTarget[faceIndex][level]) { ID3D11Device *device = mRenderer->getDevice(); @@ -865,10 +1086,8 @@ ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mi srvDesc.Format = format; // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six 2D textures - bool unnormalizedInteger = (d3d11::GetComponentType(mTextureFormat) == GL_INT || - d3d11::GetComponentType(mTextureFormat) == GL_UNSIGNED_INT); - - if(unnormalizedInteger) + 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; @@ -897,14 +1116,25 @@ ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mi return SRV; } -void TextureStorage11_Cube::generateMipmap(int faceIndex, int level) +void TextureStorage11_Cube::generateMipmaps() { - invalidateSwizzleCacheLevel(level); + // Base level must already be defined - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTargetFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTargetFace(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level)); + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 1; level < getLevelCount(); level++) + { + invalidateSwizzleCacheLevel(level); + + gl::ImageIndex srcIndex = gl::ImageIndex::MakeCube(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1); + gl::ImageIndex destIndex = gl::ImageIndex::MakeCube(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level); - generateMipmapLayer(source, dest); + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex)); + + generateMipmapLayer(source, dest); + } + } } ID3D11Resource *TextureStorage11_Cube::getSwizzleTexture() @@ -976,11 +1206,6 @@ ID3D11RenderTargetView *TextureStorage11_Cube::getSwizzleRenderTarget(int mipLev } } -unsigned int TextureStorage11_Cube::getTextureLevelDepth(int mipLevel) const -{ - return 6; -} - TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) @@ -990,17 +1215,19 @@ TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalform for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) { + mAssociatedImages[i] = NULL; mLevelRenderTargets[i] = NULL; mSwizzleRenderTargets[i] = NULL; } - mTextureFormat = gl_d3d11::GetTexFormat(internalformat); - mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat); - mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat); - mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat); - mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat); - mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat); - mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(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; // 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 @@ -1045,10 +1272,27 @@ TextureStorage11_3D::TextureStorage11_3D(Renderer *renderer, GLenum internalform mTextureDepth = desc.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); @@ -1071,6 +1315,69 @@ TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage return static_cast(storage); } +void TextureStorage11_3D::associateImage(Image11* image, int level, int layerTarget) +{ + 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(int level, int layerTarget, Image11* expectedImage) +{ + 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(int level, int layerTarget, Image11* expectedImage) +{ + 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. +void TextureStorage11_3D::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) +{ + 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. + mAssociatedImages[level]->recoverFromAssociatedStorage(); + } + } + } +} + ID3D11Resource *TextureStorage11_3D::getResource() const { return mTexture; @@ -1098,20 +1405,24 @@ ID3D11ShaderResourceView *TextureStorage11_3D::createSRV(int baseLevel, int mipL return SRV; } -RenderTarget *TextureStorage11_3D::getRenderTarget(int mipLevel) +RenderTarget *TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index) { + int mipLevel = index.mipIndex; + if (mipLevel >= 0 && mipLevel < getLevelCount()) { - if (!mLevelRenderTargets[mipLevel]) + ASSERT(mRenderTargetFormat != DXGI_FORMAT_UNKNOWN); + + if (!index.hasLayer()) { - ID3D11ShaderResourceView *srv = getSRVLevel(mipLevel); - if (!srv) + if (!mLevelRenderTargets[mipLevel]) { - return NULL; - } + ID3D11ShaderResourceView *srv = getSRVLevel(mipLevel); + if (!srv) + { + return NULL; + } - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) - { ID3D11Device *device = mRenderer->getDevice(); D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; @@ -1136,35 +1447,22 @@ RenderTarget *TextureStorage11_3D::getRenderTarget(int mipLevel) // RenderTarget will take ownership of these resources SafeRelease(rtv); } - else - { - UNREACHABLE(); - } - } - return mLevelRenderTargets[mipLevel]; - } - else - { - return NULL; - } -} - -RenderTarget *TextureStorage11_3D::getRenderTargetLayer(int mipLevel, int layer) -{ - if (mipLevel >= 0 && mipLevel < getLevelCount()) - { - LevelLayerKey key(mipLevel, layer); - if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end()) + return mLevelRenderTargets[mipLevel]; + } + else { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; + int layer = index.layerIndex; - // TODO, what kind of SRV is expected here? - ID3D11ShaderResourceView *srv = NULL; - - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + LevelLayerKey key(mipLevel, layer); + if (mLevelLayerRenderTargets.find(key) == mLevelLayerRenderTargets.end()) { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + // 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; @@ -1188,28 +1486,30 @@ RenderTarget *TextureStorage11_3D::getRenderTargetLayer(int mipLevel, int layer) SafeRelease(rtv); SafeRelease(srv); } - else - { - UNREACHABLE(); - } - } - return mLevelLayerRenderTargets[key]; - } - else - { - return NULL; + return mLevelLayerRenderTargets[key]; + } } + + return NULL; } -void TextureStorage11_3D::generateMipmap(int level) +void TextureStorage11_3D::generateMipmaps() { - invalidateSwizzleCacheLevel(level); + // Base level must already be defined + + for (int level = 1; level < getLevelCount(); level++) + { + invalidateSwizzleCacheLevel(level); + + gl::ImageIndex srcIndex = gl::ImageIndex::Make3D(level - 1); + gl::ImageIndex destIndex = gl::ImageIndex::Make3D(level); - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(srcIndex)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex)); - generateMipmapLayer(source, dest); + generateMipmapLayer(source, dest); + } } ID3D11Resource *TextureStorage11_3D::getSwizzleTexture() @@ -1279,12 +1579,6 @@ ID3D11RenderTargetView *TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel } } -unsigned int TextureStorage11_3D::getTextureLevelDepth(int mipLevel) const -{ - return std::max(mTextureDepth >> mipLevel, 1U); -} - - TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) @@ -1297,13 +1591,14 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum in mSwizzleRenderTargets[level] = NULL; } - mTextureFormat = gl_d3d11::GetTexFormat(internalformat); - mShaderResourceFormat = gl_d3d11::GetSRVFormat(internalformat); - mDepthStencilFormat = gl_d3d11::GetDSVFormat(internalformat); - mRenderTargetFormat = gl_d3d11::GetRTVFormat(internalformat); - mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalformat); - mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalformat); - mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(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; // 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 @@ -1350,10 +1645,25 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer *renderer, GLenum in mTextureDepth = desc.ArraySize; } } + + 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); @@ -1375,6 +1685,66 @@ TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray return static_cast(storage); } +void TextureStorage11_2DArray::associateImage(Image11* image, int level, int layerTarget) +{ + ASSERT(0 <= level && level < getLevelCount()); + + if (0 <= level && level < getLevelCount()) + { + LevelLayerKey key(level, layerTarget); + mAssociatedImages[key] = image; + } +} + +bool TextureStorage11_2DArray::isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) +{ + 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(int level, int layerTarget, Image11* expectedImage) +{ + 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. +void TextureStorage11_2DArray::releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) +{ + 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. + mAssociatedImages[key]->recoverFromAssociatedStorage(); + } + } + } +} + ID3D11Resource *TextureStorage11_2DArray::getResource() const { return mTexture; @@ -1404,8 +1774,13 @@ ID3D11ShaderResourceView *TextureStorage11_2DArray::createSRV(int baseLevel, int return SRV; } -RenderTarget *TextureStorage11_2DArray::getRenderTargetLayer(int mipLevel, int layer) +RenderTarget *TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index) { + ASSERT(index.hasLayer()); + + int mipLevel = index.mipIndex; + int layer = index.layerIndex; + if (mipLevel >= 0 && mipLevel < getLevelCount()) { LevelLayerKey key(mipLevel, layer); @@ -1470,15 +1845,23 @@ RenderTarget *TextureStorage11_2DArray::getRenderTargetLayer(int mipLevel, int l } } -void TextureStorage11_2DArray::generateMipmap(int level) +void TextureStorage11_2DArray::generateMipmaps() { - invalidateSwizzleCacheLevel(level); - for (unsigned int layer = 0; layer < mTextureDepth; layer++) + // Base level must already be defined + + for (int level = 0; level < getLevelCount(); level++) { - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level - 1, layer)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level, layer)); + invalidateSwizzleCacheLevel(level); + for (unsigned int layer = 0; layer < mTextureDepth; layer++) + { + gl::ImageIndex sourceIndex = gl::ImageIndex::Make2DArray(level - 1, layer); + gl::ImageIndex destIndex = gl::ImageIndex::Make2DArray(level, layer); - generateMipmapLayer(source, dest); + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(sourceIndex)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(destIndex)); + + generateMipmapLayer(source, dest); + } } } @@ -1551,9 +1934,4 @@ ID3D11RenderTargetView *TextureStorage11_2DArray::getSwizzleRenderTarget(int mip } } -unsigned int TextureStorage11_2DArray::getTextureLevelDepth(int mipLevel) const -{ - return mTextureDepth; -} - } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h index 6be7bac8e2..9d63b2699d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h @@ -11,8 +11,16 @@ #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; @@ -20,6 +28,7 @@ class RenderTarget11; class Renderer; class Renderer11; class SwapChain11; +class Image11; class TextureStorage11 : public TextureStorage { @@ -34,12 +43,9 @@ class TextureStorage11 : public TextureStorage virtual ID3D11Resource *getResource() const = 0; virtual ID3D11ShaderResourceView *getSRV(const gl::SamplerState &samplerState); - virtual RenderTarget *getRenderTarget(int level) { return NULL; } - virtual RenderTarget *getRenderTargetFace(GLenum faceTarget, int level) { return NULL; } - virtual RenderTarget *getRenderTargetLayer(int mipLevel, int layer) { return NULL; } + virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index) = 0; - virtual void generateMipmap(int level) {}; - virtual void generateMipmap(int face, int level) {}; + virtual void generateMipmaps() = 0; virtual int getTopLevel() const; virtual bool isRenderTarget() const; @@ -47,7 +53,7 @@ class TextureStorage11 : public TextureStorage virtual int getLevelCount() const; UINT getSubresourceIndex(int mipLevel, int layerTarget) const; - void generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); + gl::Error generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); void invalidateSwizzleCacheLevel(int mipLevel); void invalidateSwizzleCache(); @@ -55,6 +61,15 @@ class TextureStorage11 : public TextureStorage int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); + bool copySubresourceLevel(ID3D11Resource* dstTexture, unsigned int dstSubresource, int level, + int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth); + + virtual void associateImage(Image11* image, int level, int layerTarget) = 0; + virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage) = 0; + virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage) = 0; + virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage) = 0; + protected: TextureStorage11(Renderer *renderer, UINT bindFlags); void generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest); @@ -70,8 +85,6 @@ class TextureStorage11 : public TextureStorage void verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); - virtual unsigned int getTextureLevelDepth(int mipLevel) const = 0; - Renderer11 *mRenderer; int mTopLevel; unsigned int mMipLevels; @@ -148,16 +161,19 @@ class TextureStorage11_2D : public TextureStorage11 static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage); virtual ID3D11Resource *getResource() const; - virtual RenderTarget *getRenderTarget(int level); + virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); + + virtual void generateMipmaps(); - virtual void generateMipmap(int level); + virtual void associateImage(Image11* image, int level, int layerTarget); + virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage); + virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage); + virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage); protected: virtual ID3D11Resource *getSwizzleTexture(); virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); - virtual unsigned int getTextureLevelDepth(int mipLevel) const; - private: DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D); @@ -168,6 +184,8 @@ class TextureStorage11_2D : public TextureStorage11 ID3D11Texture2D *mSwizzleTexture; ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; }; class TextureStorage11_Cube : public TextureStorage11 @@ -179,16 +197,19 @@ class TextureStorage11_Cube : public TextureStorage11 static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage); virtual ID3D11Resource *getResource() const; - virtual RenderTarget *getRenderTargetFace(GLenum faceTarget, int level); + virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); - virtual void generateMipmap(int faceIndex, int level); + virtual void generateMipmaps(); + + virtual void associateImage(Image11* image, int level, int layerTarget); + virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage); + virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage); + virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage); protected: virtual ID3D11Resource *getSwizzleTexture(); virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); - virtual unsigned int getTextureLevelDepth(int mipLevel) const; - private: DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube); @@ -199,6 +220,8 @@ class TextureStorage11_Cube : public TextureStorage11 ID3D11Texture2D *mSwizzleTexture; ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + Image11 *mAssociatedImages[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; }; class TextureStorage11_3D : public TextureStorage11 @@ -211,17 +234,21 @@ class TextureStorage11_3D : public TextureStorage11 static TextureStorage11_3D *makeTextureStorage11_3D(TextureStorage *storage); virtual ID3D11Resource *getResource() const; - virtual RenderTarget *getRenderTarget(int mipLevel); - virtual RenderTarget *getRenderTargetLayer(int mipLevel, int layer); - virtual void generateMipmap(int level); + // Handles both layer and non-layer RTs + virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); + + virtual void generateMipmaps(); + + virtual void associateImage(Image11* image, int level, int layerTarget); + virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage); + virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage); + virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage); protected: virtual ID3D11Resource *getSwizzleTexture(); virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); - virtual unsigned int getTextureLevelDepth(int mipLevel) const; - private: DISALLOW_COPY_AND_ASSIGN(TextureStorage11_3D); @@ -236,6 +263,8 @@ class TextureStorage11_3D : public TextureStorage11 ID3D11Texture3D *mTexture; ID3D11Texture3D *mSwizzleTexture; ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + Image11 *mAssociatedImages[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; }; class TextureStorage11_2DArray : public TextureStorage11 @@ -248,16 +277,19 @@ class TextureStorage11_2DArray : public TextureStorage11 static TextureStorage11_2DArray *makeTextureStorage11_2DArray(TextureStorage *storage); virtual ID3D11Resource *getResource() const; - virtual RenderTarget *getRenderTargetLayer(int mipLevel, int layer); + virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); + + virtual void generateMipmaps(); - virtual void generateMipmap(int level); + virtual void associateImage(Image11* image, int level, int layerTarget); + virtual void disassociateImage(int level, int layerTarget, Image11* expectedImage); + virtual bool isAssociatedImageValid(int level, int layerTarget, Image11* expectedImage); + virtual void releaseAssociatedImage(int level, int layerTarget, Image11* incomingImage); protected: virtual ID3D11Resource *getSwizzleTexture(); virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); - virtual unsigned int getTextureLevelDepth(int mipLevel) const; - private: DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2DArray); @@ -271,6 +303,9 @@ class TextureStorage11_2DArray : public TextureStorage11 ID3D11Texture2D *mSwizzleTexture; ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + typedef std::map ImageMap; + ImageMap mAssociatedImages; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp index 2f47ec0a67..9bc5b1d2d1 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -9,11 +8,10 @@ #include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" #include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" - -#include "libGLESv2/Buffer.h" #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" -#include "libGLESv2/VertexAttribute.h" #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/Buffer.h" +#include "libGLESv2/VertexAttribute.h" namespace rx { @@ -30,7 +28,7 @@ VertexBuffer11::~VertexBuffer11() SafeRelease(mBuffer); } -bool VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) +gl::Error VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) { SafeRelease(mBuffer); @@ -51,13 +49,14 @@ bool VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); if (FAILED(result)) { - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size); } } mBufferSize = size; mDynamicUsage = dynamicUsage; - return true; + + return gl::Error(GL_NO_ERROR); } VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) @@ -66,66 +65,62 @@ VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) return static_cast(vetexBuffer); } -bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int offset) +gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int offset) { - if (mBuffer) + if (!mBuffer) { - gl::Buffer *buffer = attrib.buffer.get(); - int inputStride = ComputeVertexAttributeStride(attrib); - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + } - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Vertex buffer map failed with error 0x%08x", result); - return false; - } + gl::Buffer *buffer = attrib.buffer.get(); + int inputStride = ComputeVertexAttributeStride(attrib); + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - char* output = reinterpret_cast(mappedResource.pData) + offset; + 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); + } - const char *input = NULL; - if (attrib.enabled) + uint8_t *output = reinterpret_cast(mappedResource.pData) + offset; + + const uint8_t *input = NULL; + if (attrib.enabled) + { + if (buffer) { - if (buffer) - { - Buffer11 *storage = Buffer11::makeBuffer11(buffer->getImplementation()); - input = static_cast(storage->getData()) + static_cast(attrib.offset); - } - else - { - input = static_cast(attrib.pointer); - } + Buffer11 *storage = Buffer11::makeBuffer11(buffer->getImplementation()); + input = static_cast(storage->getData()) + static_cast(attrib.offset); } else { - input = reinterpret_cast(currentValue.FloatValues); - } - - if (instances == 0 || attrib.divisor == 0) - { - input += inputStride * start; + input = static_cast(attrib.pointer); } - - gl::VertexFormat vertexFormat(attrib, currentValue.Type); - VertexCopyFunction conversionFunc = gl_d3d11::GetVertexCopyFunction(vertexFormat); - ASSERT(conversionFunc != NULL); - conversionFunc(input, inputStride, count, output); - - dxContext->Unmap(mBuffer, 0); - - return true; } else { - ERR("Vertex buffer not initialized."); - return false; + 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); } -bool VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, - GLsizei instances, unsigned int *outSpaceRequired) const +gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, + GLsizei instances, unsigned int *outSpaceRequired) const { unsigned int elementCount = 0; if (attrib.enabled) @@ -136,30 +131,25 @@ bool VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei } else { - if (static_cast(instances) < std::numeric_limits::max() - (attrib.divisor - 1)) - { - // Round up - elementCount = rx::roundUp(static_cast(instances), attrib.divisor); - } - else - { - elementCount = instances / attrib.divisor; - } + // Round up to divisor, if possible + elementCount = rx::UnsignedCeilDivide(static_cast(instances), attrib.divisor); } gl::VertexFormat vertexFormat(attrib); - unsigned int elementSize = static_cast(gl_d3d11::GetVertexElementSize(vertexFormat)); + 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 true; + return gl::Error(GL_NO_ERROR); } else { - return false; + return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow."); } } else @@ -169,7 +159,7 @@ bool VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei { *outSpaceRequired = elementSize * 4; } - return true; + return gl::Error(GL_NO_ERROR); } } @@ -178,7 +168,7 @@ unsigned int VertexBuffer11::getBufferSize() const return mBufferSize; } -bool VertexBuffer11::setBufferSize(unsigned int size) +gl::Error VertexBuffer11::setBufferSize(unsigned int size) { if (size > mBufferSize) { @@ -186,33 +176,29 @@ bool VertexBuffer11::setBufferSize(unsigned int size) } else { - return true; + return gl::Error(GL_NO_ERROR); } } -bool VertexBuffer11::discard() +gl::Error VertexBuffer11::discard() { - if (mBuffer) + if (!mBuffer) { - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Vertex buffer map failed with error 0x%08x", result); - return false; - } + return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + } - dxContext->Unmap(mBuffer, 0); + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - return true; - } - else + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) { - ERR("Vertex buffer not initialized."); - return false; + 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 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h index c2a5aa7afd..0e10da1df8 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h @@ -21,19 +21,19 @@ class VertexBuffer11 : public VertexBuffer explicit VertexBuffer11(rx::Renderer11 *const renderer); virtual ~VertexBuffer11(); - virtual bool initialize(unsigned int size, bool dynamicUsage); + virtual gl::Error initialize(unsigned int size, bool dynamicUsage); static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer); - virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int offset); + virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int offset); - virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, - unsigned int *outSpaceRequired) const; + virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, + unsigned int *outSpaceRequired) const; virtual unsigned int getBufferSize() const; - virtual bool setBufferSize(unsigned int size); - virtual bool discard(); + virtual gl::Error setBufferSize(unsigned int size); + virtual gl::Error discard(); ID3D11Buffer *getBuffer() const; 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 c991fd4991..c07828757d 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -18,384 +17,236 @@ namespace rx { -struct D3D11FormatInfo +namespace d3d11 { - DXGI_FORMAT mTexFormat; - DXGI_FORMAT mSRVFormat; - DXGI_FORMAT mRTVFormat; - DXGI_FORMAT mDSVFormat; - - D3D11FormatInfo() - : mTexFormat(DXGI_FORMAT_UNKNOWN), mDSVFormat(DXGI_FORMAT_UNKNOWN), mRTVFormat(DXGI_FORMAT_UNKNOWN), mSRVFormat(DXGI_FORMAT_UNKNOWN) - { } - D3D11FormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat) - : mTexFormat(texFormat), mDSVFormat(dsvFormat), mRTVFormat(rtvFormat), mSRVFormat(srvFormat) - { } -}; +typedef std::map DXGIToESFormatMap; -// 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::pair D3D11ES3FormatPair; -typedef std::map D3D11ES3FormatMap; +inline void AddDXGIToESEntry(DXGIToESFormatMap *map, DXGI_FORMAT key, GLenum value) +{ + map->insert(std::make_pair(key, value)); +} -static D3D11ES3FormatMap BuildD3D11FormatMap() +static DXGIToESFormatMap BuildDXGIToESFormatMap() { - D3D11ES3FormatMap map; + DXGIToESFormatMap map; - // | GL internal format | | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | - map.insert(D3D11ES3FormatPair(GL_NONE, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R8, D3D11FormatInfo(DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R8_SNORM, D3D11FormatInfo(DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_R8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG8, D3D11FormatInfo(DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG8_SNORM, D3D11FormatInfo(DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_R8G8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB8, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB8_SNORM, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB565, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA4, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB5_A1, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA8, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA8_SNORM, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB10_A2, D3D11FormatInfo(DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_R10G10B10A2_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB10_A2UI, D3D11FormatInfo(DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_R10G10B10A2_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_SRGB8, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_SRGB8_ALPHA8, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R16F, D3D11FormatInfo(DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG16F, D3D11FormatInfo(DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_R16G16_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB16F, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA16F, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R32F, D3D11FormatInfo(DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG32F, D3D11FormatInfo(DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_R32G32_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB32F, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA32F, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R11F_G11F_B10F, D3D11FormatInfo(DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_R11G11B10_FLOAT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB9_E5, D3D11FormatInfo(DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R8I, D3D11FormatInfo(DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_R8_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R8UI, D3D11FormatInfo(DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_R8_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R16I, D3D11FormatInfo(DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_R16_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R16UI, D3D11FormatInfo(DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_R16_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R32I, D3D11FormatInfo(DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_R32_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_R32UI, D3D11FormatInfo(DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_R32_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG8I, D3D11FormatInfo(DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_R8G8_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG8UI, D3D11FormatInfo(DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_R8G8_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG16I, D3D11FormatInfo(DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_R16G16_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG16UI, D3D11FormatInfo(DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_R16G16_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG32I, D3D11FormatInfo(DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_R32G32_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RG32UI, D3D11FormatInfo(DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_R32G32_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB8I, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB8UI, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB16I, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB16UI, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB32I, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB32UI, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA8I, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA8UI, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA16I, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA16UI, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA32I, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA32UI, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_UNKNOWN))); + AddDXGIToESEntry(&map, DXGI_FORMAT_UNKNOWN, GL_NONE); - // Unsized formats, TODO: Are types of float and half float allowed for the unsized types? Would it change the DXGI format? - map.insert(D3D11ES3FormatPair(GL_ALPHA, D3D11FormatInfo(DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_LUMINANCE, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_LUMINANCE_ALPHA, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGB, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_RGBA, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_BGRA_EXT, D3D11FormatInfo(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN))); + 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); - // From GL_EXT_texture_storage - // | GL internal format | | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format | - map.insert(D3D11ES3FormatPair(GL_ALPHA8_EXT, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_LUMINANCE8_EXT, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_ALPHA32F_EXT, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_LUMINANCE32F_EXT, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_ALPHA16F_EXT, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_LUMINANCE16F_EXT, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_LUMINANCE8_ALPHA8_EXT, D3D11FormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_LUMINANCE_ALPHA32F_EXT, D3D11FormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_LUMINANCE_ALPHA16F_EXT, D3D11FormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_BGRA8_EXT, D3D11FormatInfo(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_BGRA4_ANGLEX, D3D11FormatInfo(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); - map.insert(D3D11ES3FormatPair(GL_BGR5_A1_ANGLEX, D3D11FormatInfo(DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_UNKNOWN ))); + 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); - // Depth stencil formats - map.insert(D3D11ES3FormatPair(GL_DEPTH_COMPONENT16, D3D11FormatInfo(DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D16_UNORM ))); - map.insert(D3D11ES3FormatPair(GL_DEPTH_COMPONENT24, D3D11FormatInfo(DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ))); - map.insert(D3D11ES3FormatPair(GL_DEPTH_COMPONENT32F, D3D11FormatInfo(DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT ))); - map.insert(D3D11ES3FormatPair(GL_DEPTH24_STENCIL8, D3D11FormatInfo(DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ))); - map.insert(D3D11ES3FormatPair(GL_DEPTH32F_STENCIL8, D3D11FormatInfo(DXGI_FORMAT_R32G8X24_TYPELESS, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D32_FLOAT_S8X24_UINT))); - map.insert(D3D11ES3FormatPair(GL_STENCIL_INDEX8, D3D11FormatInfo(DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_X24_TYPELESS_G8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ))); + 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); - // 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. - map.insert(D3D11ES3FormatPair(GL_DEPTH_COMPONENT32_OES, D3D11FormatInfo(DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT ))); + 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); - // 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 | - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_R11_EAC, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_SIGNED_R11_EAC, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RG11_EAC, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_SIGNED_RG11_EAC, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGB8_ETC2, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_SRGB8_ETC2, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGBA8_ETC2_EAC, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, D3D11FormatInfo(DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UNORM, GL_RGB10_A2); + AddDXGIToESEntry(&map, DXGI_FORMAT_R10G10B10A2_UINT, GL_RGB10_A2UI); - // From GL_EXT_texture_compression_dxt1 - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3D11FormatInfo(DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3D11FormatInfo(DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16_FLOAT, GL_R16F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16_FLOAT, GL_RG16F); + AddDXGIToESEntry(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, GL_RGBA16F); - // From GL_ANGLE_texture_compression_dxt3 - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3D11FormatInfo(DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + 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); - // From GL_ANGLE_texture_compression_dxt5 - map.insert(D3D11ES3FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3D11FormatInfo(DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN))); + 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; } -static bool GetD3D11FormatInfo(GLenum internalFormat, D3D11FormatInfo *outFormatInfo) +struct D3D11FastCopyFormat { - static const D3D11ES3FormatMap formatMap = BuildD3D11FormatMap(); - D3D11ES3FormatMap::const_iterator iter = formatMap.find(internalFormat); - if (iter != formatMap.end()) - { - if (outFormatInfo) - { - *outFormatInfo = iter->second; - } - return true; - } - else + 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 false; + return memcmp(this, &other, sizeof(D3D11FastCopyFormat)) < 0; } -} +}; -// 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 InternalFormatTypePair; -typedef std::pair D3D11LoadFunctionPair; -typedef std::map D3D11LoadFunctionMap; +typedef std::multimap D3D11FastCopyMap; -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) +static D3D11FastCopyMap BuildFastCopyMap() { - UNIMPLEMENTED(); -} + D3D11FastCopyMap map; -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(); -} + map.insert(std::make_pair(DXGI_FORMAT_B8G8R8A8_UNORM, D3D11FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8))); -// 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->insert(D3D11LoadFunctionPair(InternalFormatTypePair(internalFormat, type), loadFunc)); + return map; } -D3D11LoadFunctionMap buildD3D11LoadFunctionMap() +struct DXGIDepthStencilInfo { - 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 ); + unsigned int depthBits; + unsigned int depthOffset; + unsigned int stencilBits; + unsigned int stencilOffset; +}; - // 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 ); +typedef std::map DepthStencilInfoMap; +typedef std::pair DepthStencilInfoPair; - // 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 ); +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; - // 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 ); + map->insert(std::make_pair(format, info)); +} - // From GL_EXT_texture_storage - insertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadA8ToBGRA8 ); - 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 ); +static DepthStencilInfoMap BuildDepthStencilInfoMap() +{ + DepthStencilInfoMap map; - // From GL_ANGLE_depth_texture - insertLoadFunction(&map, GL_DEPTH_COMPONENT32_OES, GL_UNSIGNED_INT, LoadR32ToR24G8 ); + 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); - // 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 ); + 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); - // 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 ); + 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); - // 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>); + 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); - // From GL_ANGLE_texture_compression_dxt3 - insertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>); + return map; +} - // From GL_ANGLE_texture_compression_dxt5 - insertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>); +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() +{ +} - return map; +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; } -// A map to determine the pixel size and mipmap generation function of a given DXGI format -struct DXGIFormatInfo +void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, + GLenum componentType, MipGenerationFunction mipFunc, ColorReadFunction readFunc) { - GLuint mPixelBits; - GLuint mBlockWidth; - GLuint mBlockHeight; - GLenum mComponentType; + DXGIFormat info; + info.pixelBytes = pixelBits / 8; + info.blockWidth = blockWidth; + info.blockHeight = blockHeight; - MipGenerationFunction mMipGenerationFunction; - ColorReadFunction mColorReadFunction; + 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; + } - DXGIFormatInfo() - : mPixelBits(0), mBlockWidth(0), mBlockHeight(0), mComponentType(GL_NONE), mMipGenerationFunction(NULL), - mColorReadFunction(NULL) - { } + static const DXGIToESFormatMap dxgiToESMap = BuildDXGIToESFormatMap(); + DXGIToESFormatMap::const_iterator dxgiToESIter = dxgiToESMap.find(dxgiFormat); + info.internalFormat = (dxgiToESIter != dxgiToESMap.end()) ? dxgiToESIter->second : GL_NONE; - DXGIFormatInfo(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, GLenum componentType, - MipGenerationFunction mipFunc, ColorReadFunction readFunc) - : mPixelBits(pixelBits), mBlockWidth(blockWidth), mBlockHeight(blockHeight), mComponentType(componentType), - mMipGenerationFunction(mipFunc), mColorReadFunction(readFunc) - { } -}; + info.componentType = componentType; -typedef std::map DXGIFormatInfoMap; + info.mipGenerationFunction = mipFunc; + info.colorReadFunction = readFunc; -void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, - GLenum componentType, MipGenerationFunction mipFunc, ColorReadFunction readFunc) -{ - map->insert(std::make_pair(dxgiFormat, DXGIFormatInfo(pixelBits, blockWidth, blockHeight, componentType, mipFunc, 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 + // | 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); @@ -473,240 +324,38 @@ static DXGIFormatInfoMap BuildDXGIFormatInfoMap() return map; } -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; -} - -static const DXGIToESFormatMap &GetDXGIToESFormatMap() -{ - static const DXGIToESFormatMap map = BuildDXGIToESFormatMap(); - return map; -} - -static const DXGIFormatInfoMap &GetDXGIFormatInfoMap() +const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format) { static const DXGIFormatInfoMap infoMap = BuildDXGIFormatInfoMap(); - return infoMap; -} - -static bool GetDXGIFormatInfo(DXGI_FORMAT format, DXGIFormatInfo *outFormatInfo) -{ - const DXGIFormatInfoMap &infoMap = GetDXGIFormatInfoMap(); DXGIFormatInfoMap::const_iterator iter = infoMap.find(format); if (iter != infoMap.end()) { - if (outFormatInfo) - { - *outFormatInfo = iter->second; - } - return true; - } - else - { - return false; - } -} - -static d3d11::DXGIFormatSet BuildAllDXGIFormatSet() -{ - d3d11::DXGIFormatSet set; - - const DXGIFormatInfoMap &infoMap = GetDXGIFormatInfoMap(); - for (DXGIFormatInfoMap::const_iterator i = infoMap.begin(); i != infoMap.end(); ++i) - { - set.insert(i->first); - } - - return set; -} - -struct D3D11FastCopyFormat -{ - DXGI_FORMAT mSourceFormat; - GLenum mDestFormat; - GLenum mDestType; - - D3D11FastCopyFormat(DXGI_FORMAT sourceFormat, GLenum destFormat, GLenum destType) - : mSourceFormat(sourceFormat), mDestFormat(destFormat), mDestType(destType) - { } - - bool operator<(const D3D11FastCopyFormat& other) const - { - return memcmp(this, &other, sizeof(D3D11FastCopyFormat)) < 0; - } -}; - -typedef std::map D3D11FastCopyMap; -typedef std::pair D3D11FastCopyPair; - -static D3D11FastCopyMap BuildFastCopyMap() -{ - D3D11FastCopyMap map; - - map.insert(D3D11FastCopyPair(D3D11FastCopyFormat(DXGI_FORMAT_B8G8R8A8_UNORM, GL_RGBA, GL_UNSIGNED_BYTE), CopyBGRAUByteToRGBAUByte)); - - return map; -} - -struct DXGIDepthStencilInfo -{ - unsigned int mDepthBits; - unsigned int mDepthOffset; - unsigned int mStencilBits; - unsigned int mStencilOffset; - - DXGIDepthStencilInfo() - : mDepthBits(0), mDepthOffset(0), mStencilBits(0), mStencilOffset(0) - { } - - DXGIDepthStencilInfo(unsigned int depthBits, unsigned int depthOffset, unsigned int stencilBits, unsigned int stencilOffset) - : mDepthBits(depthBits), mDepthOffset(depthOffset), mStencilBits(stencilBits), mStencilOffset(stencilOffset) - { } -}; - -typedef std::map DepthStencilInfoMap; -typedef std::pair DepthStencilInfoPair; - -static DepthStencilInfoMap BuildDepthStencilInfoMap() -{ - DepthStencilInfoMap map; - - map.insert(DepthStencilInfoPair(DXGI_FORMAT_R16_TYPELESS, DXGIDepthStencilInfo(16, 0, 0, 0))); - map.insert(DepthStencilInfoPair(DXGI_FORMAT_R16_UNORM, DXGIDepthStencilInfo(16, 0, 0, 0))); - map.insert(DepthStencilInfoPair(DXGI_FORMAT_D16_UNORM, DXGIDepthStencilInfo(16, 0, 0, 0))); - - map.insert(DepthStencilInfoPair(DXGI_FORMAT_R24G8_TYPELESS, DXGIDepthStencilInfo(24, 0, 8, 24))); - map.insert(DepthStencilInfoPair(DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGIDepthStencilInfo(24, 0, 8, 24))); - map.insert(DepthStencilInfoPair(DXGI_FORMAT_D24_UNORM_S8_UINT, DXGIDepthStencilInfo(24, 0, 8, 24))); - - map.insert(DepthStencilInfoPair(DXGI_FORMAT_R32_TYPELESS, DXGIDepthStencilInfo(32, 0, 0, 0))); - map.insert(DepthStencilInfoPair(DXGI_FORMAT_R32_FLOAT, DXGIDepthStencilInfo(32, 0, 0, 0))); - map.insert(DepthStencilInfoPair(DXGI_FORMAT_D32_FLOAT, DXGIDepthStencilInfo(32, 0, 0, 0))); - - map.insert(DepthStencilInfoPair(DXGI_FORMAT_R32G8X24_TYPELESS, DXGIDepthStencilInfo(32, 0, 8, 32))); - map.insert(DepthStencilInfoPair(DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, DXGIDepthStencilInfo(32, 0, 8, 32))); - map.insert(DepthStencilInfoPair(DXGI_FORMAT_D32_FLOAT_S8X24_UINT, DXGIDepthStencilInfo(32, 0, 8, 32))); - - return map; -} - -static const DepthStencilInfoMap &GetDepthStencilInfoMap() -{ - static const DepthStencilInfoMap infoMap = BuildDepthStencilInfoMap(); - return infoMap; -} - -bool GetDepthStencilInfo(DXGI_FORMAT format, DXGIDepthStencilInfo *outDepthStencilInfo) -{ - const DepthStencilInfoMap& infoMap = GetDepthStencilInfoMap(); - DepthStencilInfoMap::const_iterator iter = infoMap.find(format); - if (iter != infoMap.end()) - { - if (outDepthStencilInfo) - { - *outDepthStencilInfo = iter->second; - } - return true; + return iter->second; } else { - return false; + static DXGIFormat defaultInfo; + return defaultInfo; } } struct SwizzleSizeType { - unsigned int mMaxComponentSize; - GLenum mComponentType; + size_t maxComponentSize; + GLenum componentType; SwizzleSizeType() - : mMaxComponentSize(0), mComponentType(GL_NONE) + : maxComponentSize(0), componentType(GL_NONE) { } - SwizzleSizeType(unsigned int maxComponentSize, GLenum componentType) - : mMaxComponentSize(maxComponentSize), mComponentType(componentType) + SwizzleSizeType(size_t maxComponentSize, GLenum componentType) + : maxComponentSize(maxComponentSize), componentType(componentType) { } bool operator<(const SwizzleSizeType& other) const { - return (mMaxComponentSize != other.mMaxComponentSize) ? (mMaxComponentSize < other.mMaxComponentSize) - : (mComponentType < other.mComponentType); + return (maxComponentSize != other.maxComponentSize) ? (maxComponentSize < other.maxComponentSize) + : (componentType < other.componentType); } }; @@ -752,6 +401,7 @@ static SwizzleInfoMap BuildSwizzleInfoMap() return map; } + typedef std::pair InternalFormatInitializerPair; typedef std::map InternalFormatInitializerMap; @@ -771,433 +421,480 @@ static InternalFormatInitializerMap BuildInternalFormatInitializerMap() map.insert(InternalFormatInitializerPair(GL_RGB32UI, Initialize4ComponentData )); map.insert(InternalFormatInitializerPair(GL_RGB32I, Initialize4ComponentData )); - return map; + 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(); } -static const SwizzleInfoMap &GetSwizzleInfoMap() +// A helper function to insert data into the D3D11LoadFunctionMap with fewer characters. +static inline void InsertLoadFunction(D3D11LoadFunctionMap *map, GLenum internalFormat, GLenum type, + LoadImageFunction loadFunc) { - static const SwizzleInfoMap map = BuildSwizzleInfoMap(); - return map; + (*map)[internalFormat].push_back(TypeLoadFunctionPair(type, loadFunc)); } -static const SwizzleFormatInfo GetSwizzleFormatInfo(GLenum internalFormat) +D3D11LoadFunctionMap BuildD3D11LoadFunctionMap() { - // Get the maximum sized component - unsigned int maxBits = 1; + D3D11LoadFunctionMap map; - if (gl::IsFormatCompressed(internalFormat)) - { - unsigned int compressedBitsPerBlock = gl::GetPixelBytes(internalFormat) * 8; - unsigned int blockSize = gl::GetCompressedBlockWidth(internalFormat) * - gl::GetCompressedBlockHeight(internalFormat); - maxBits = std::max(compressedBitsPerBlock / blockSize, maxBits); - } - else - { - maxBits = std::max(maxBits, gl::GetAlphaBits( internalFormat)); - maxBits = std::max(maxBits, gl::GetRedBits( internalFormat)); - maxBits = std::max(maxBits, gl::GetGreenBits( internalFormat)); - maxBits = std::max(maxBits, gl::GetBlueBits( internalFormat)); - maxBits = std::max(maxBits, gl::GetLuminanceBits(internalFormat)); - maxBits = std::max(maxBits, gl::GetDepthBits( internalFormat)); - } + // | 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 ); - maxBits = roundUp(maxBits, 8U); + // 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 ); - GLenum componentType = gl::GetComponentType(internalFormat); + // 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 ); - const SwizzleInfoMap &map = GetSwizzleInfoMap(); - SwizzleInfoMap::const_iterator iter = map.find(SwizzleSizeType(maxBits, componentType)); + // 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 ); - if (iter != map.end()) - { - return iter->second; - } - else - { - UNREACHABLE(); - static const SwizzleFormatInfo defaultFormatInfo; - return defaultFormatInfo; - } -} + // 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 ); -static const InternalFormatInitializerMap &GetInternalFormatInitializerMap() -{ - static const InternalFormatInitializerMap map = BuildInternalFormatInitializerMap(); - return map; -} + // From GL_ANGLE_depth_texture + InsertLoadFunction(&map, GL_DEPTH_COMPONENT32_OES, GL_UNSIGNED_INT, LoadR32ToR24G8 ); -namespace d3d11 -{ + // 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 ); -MipGenerationFunction GetMipGenerationFunction(DXGI_FORMAT format) -{ - DXGIFormatInfo formatInfo; - if (GetDXGIFormatInfo(format, &formatInfo)) - { - return formatInfo.mMipGenerationFunction; - } - else - { - UNREACHABLE(); - return NULL; - } -} + // 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 ); -LoadImageFunction GetImageLoadFunction(GLenum internalFormat, GLenum type) -{ - static const D3D11LoadFunctionMap loadImageMap = buildD3D11LoadFunctionMap(); - D3D11LoadFunctionMap::const_iterator iter = loadImageMap.find(InternalFormatTypePair(internalFormat, type)); - if (iter != loadImageMap.end()) - { - return iter->second; - } - else - { - UNREACHABLE(); - return NULL; - } -} + // 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>); -GLuint GetFormatPixelBytes(DXGI_FORMAT format) -{ - DXGIFormatInfo dxgiFormatInfo; - if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) - { - return dxgiFormatInfo.mPixelBits / 8; - } - else - { - UNREACHABLE(); - return 0; - } -} + // From GL_ANGLE_texture_compression_dxt3 + InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>); -GLuint GetBlockWidth(DXGI_FORMAT format) -{ - DXGIFormatInfo dxgiFormatInfo; - if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) - { - return dxgiFormatInfo.mBlockWidth; - } - else - { - UNREACHABLE(); - return 0; - } -} + // From GL_ANGLE_texture_compression_dxt5 + InsertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>); -GLuint GetBlockHeight(DXGI_FORMAT format) -{ - DXGIFormatInfo dxgiFormatInfo; - if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) - { - return dxgiFormatInfo.mBlockHeight; - } - else - { - UNREACHABLE(); - return 0; - } + return map; } -GLenum GetComponentType(DXGI_FORMAT format) +// 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() { - DXGIFormatInfo dxgiFormatInfo; - if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) - { - return dxgiFormatInfo.mComponentType; - } - else - { - UNREACHABLE(); - return GL_NONE; - } } -GLuint GetDepthBits(DXGI_FORMAT format) +static inline void InsertD3D11FormatInfo(D3D11ES3FormatMap *map, GLenum internalFormat, DXGI_FORMAT texFormat, + DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat) { - DXGIDepthStencilInfo dxgiDSInfo; - if (GetDepthStencilInfo(format, &dxgiDSInfo)) - { - return dxgiDSInfo.mDepthBits; - } - else - { - // Since the depth stencil info map does not contain all used DXGI formats, - // we should not assert that the format exists - return 0; - } -} + TextureFormat info; + info.texFormat = texFormat; + info.srvFormat = srvFormat; + info.rtvFormat = rtvFormat; + info.dsvFormat = dsvFormat; -GLuint GetDepthOffset(DXGI_FORMAT format) -{ - DXGIDepthStencilInfo dxgiDSInfo; - if (GetDepthStencilInfo(format, &dxgiDSInfo)) + // 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) { - return dxgiDSInfo.mDepthOffset; + info.renderFormat = dsvFormat; } - else + else if (rtvFormat != DXGI_FORMAT_UNKNOWN) { - // Since the depth stencil info map does not contain all used DXGI formats, - // we should not assert that the format exists - return 0; + info.renderFormat = rtvFormat; } -} - -GLuint GetStencilBits(DXGI_FORMAT format) -{ - DXGIDepthStencilInfo dxgiDSInfo; - if (GetDepthStencilInfo(format, &dxgiDSInfo)) + else if (texFormat != DXGI_FORMAT_UNKNOWN) { - return dxgiDSInfo.mStencilBits; + info.renderFormat = texFormat; } else { - // Since the depth stencil info map does not contain all used DXGI formats, - // we should not assert that the format exists - return 0; + info.renderFormat = DXGI_FORMAT_UNKNOWN; } -} -GLuint GetStencilOffset(DXGI_FORMAT format) -{ - DXGIDepthStencilInfo dxgiDSInfo; - if (GetDepthStencilInfo(format, &dxgiDSInfo)) + // Compute the swizzle formats + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + if (internalFormat != GL_NONE && formatInfo.pixelBytes > 0) { - return dxgiDSInfo.mStencilOffset; - } - else - { - // Since the depth stencil info map does not contain all used DXGI formats, - // we should not assert that the format exists - return 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); + } -void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) -{ - DXGIFormatInfo dxgiFormatInfo; - if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) - { - int upsampleCount = 0; + maxBits = roundUp(maxBits, 8U); - GLsizei blockWidth = dxgiFormatInfo.mBlockWidth; - GLsizei blockHeight = dxgiFormatInfo.mBlockHeight; + static const SwizzleInfoMap swizzleMap = BuildSwizzleInfoMap(); + SwizzleInfoMap::const_iterator swizzleIter = swizzleMap.find(SwizzleSizeType(maxBits, formatInfo.componentType)); + ASSERT(swizzleIter != swizzleMap.end()); - // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already. - if (isImage || *requestWidth < blockWidth || *requestHeight < blockHeight) + const SwizzleFormatInfo &swizzleInfo = swizzleIter->second; + info.swizzleTexFormat = swizzleInfo.mTexFormat; + info.swizzleSRVFormat = swizzleInfo.mSRVFormat; + info.swizzleRTVFormat = swizzleInfo.mRTVFormat; + } + else { - while (*requestWidth % blockWidth != 0 || *requestHeight % blockHeight != 0) - { - *requestWidth <<= 1; - *requestHeight <<= 1; - upsampleCount++; - } + // The original texture format is suitable for swizzle operations + info.swizzleTexFormat = texFormat; + info.swizzleSRVFormat = srvFormat; + info.swizzleRTVFormat = rtvFormat; } - *levelOffset = upsampleCount; } else { - UNREACHABLE(); + // 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; } -} -const DXGIFormatSet &GetAllUsedDXGIFormats() -{ - static DXGIFormatSet formatSet = BuildAllDXGIFormatSet(); - return formatSet; -} + // 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; -ColorReadFunction GetColorReadFunction(DXGI_FORMAT format) -{ - DXGIFormatInfo dxgiFormatInfo; - if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) - { - return dxgiFormatInfo.mColorReadFunction; - } - else + // 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()) { - UNREACHABLE(); - return NULL; + 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)); + } } -} - -ColorCopyFunction GetFastCopyFunction(DXGI_FORMAT sourceFormat, GLenum destFormat, GLenum destType) -{ - static const D3D11FastCopyMap fastCopyMap = BuildFastCopyMap(); - D3D11FastCopyMap::const_iterator iter = fastCopyMap.find(D3D11FastCopyFormat(sourceFormat, destFormat, destType)); - return (iter != fastCopyMap.end()) ? iter->second : NULL; -} + map->insert(std::make_pair(internalFormat, info)); } -namespace gl_d3d11 +static D3D11ES3FormatMap BuildD3D11FormatMap() { + D3D11ES3FormatMap map; -DXGI_FORMAT GetTexFormat(GLenum internalFormat) -{ - D3D11FormatInfo d3d11FormatInfo; - if (GetD3D11FormatInfo(internalFormat, &d3d11FormatInfo)) - { - return d3d11FormatInfo.mTexFormat; - } - else - { - UNREACHABLE(); - return DXGI_FORMAT_UNKNOWN; - } -} + // | 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); -DXGI_FORMAT GetSRVFormat(GLenum internalFormat) -{ - D3D11FormatInfo d3d11FormatInfo; - if (GetD3D11FormatInfo(internalFormat, &d3d11FormatInfo)) - { - return d3d11FormatInfo.mSRVFormat; - } - else - { - UNREACHABLE(); - return 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); -DXGI_FORMAT GetRTVFormat(GLenum internalFormat) -{ - D3D11FormatInfo d3d11FormatInfo; - if (GetD3D11FormatInfo(internalFormat, &d3d11FormatInfo)) - { - return d3d11FormatInfo.mRTVFormat; - } - else - { - UNREACHABLE(); - return 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 ); -DXGI_FORMAT GetDSVFormat(GLenum internalFormat) -{ - D3D11FormatInfo d3d11FormatInfo; - if (GetD3D11FormatInfo(internalFormat, &d3d11FormatInfo)) - { - return d3d11FormatInfo.mDSVFormat; - } - else - { - return 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 ); -// Given a GL internal format, this function returns the DSV format if it is depth- or stencil-renderable, -// the RTV format if it is color-renderable, and the (nonrenderable) texture format otherwise. -DXGI_FORMAT GetRenderableFormat(GLenum internalFormat) -{ - DXGI_FORMAT targetFormat = GetDSVFormat(internalFormat); - if (targetFormat == DXGI_FORMAT_UNKNOWN) - targetFormat = GetRTVFormat(internalFormat); - if (targetFormat == DXGI_FORMAT_UNKNOWN) - targetFormat = GetTexFormat(internalFormat); + // 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); - return targetFormat; -} + // 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); -DXGI_FORMAT GetSwizzleTexFormat(GLint internalFormat) -{ - if (GetRTVFormat(internalFormat) == DXGI_FORMAT_UNKNOWN || gl::GetComponentCount(internalFormat) != 4) - { - const SwizzleFormatInfo &swizzleInfo = GetSwizzleFormatInfo(internalFormat); - return swizzleInfo.mTexFormat; - } - else - { - return GetTexFormat(internalFormat); - } -} + // 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); -DXGI_FORMAT GetSwizzleSRVFormat(GLint internalFormat) -{ - if (GetRTVFormat(internalFormat) == DXGI_FORMAT_UNKNOWN || gl::GetComponentCount(internalFormat) != 4) - { - const SwizzleFormatInfo &swizzleInfo = GetSwizzleFormatInfo(internalFormat); - return swizzleInfo.mSRVFormat; - } - else - { - return GetSRVFormat(internalFormat); - } -} + // 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); -DXGI_FORMAT GetSwizzleRTVFormat(GLint internalFormat) -{ - if (GetRTVFormat(internalFormat) == DXGI_FORMAT_UNKNOWN || gl::GetComponentCount(internalFormat) != 4) - { - const SwizzleFormatInfo &swizzleInfo = GetSwizzleFormatInfo(internalFormat); - return swizzleInfo.mRTVFormat; - } - else - { - return GetRTVFormat(internalFormat); - } -} + // 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); -bool RequiresTextureDataInitialization(GLint internalFormat) -{ - const InternalFormatInitializerMap &map = GetInternalFormatInitializerMap(); - return map.find(internalFormat) != map.end(); + return map; } -InitializeTextureDataFunction GetTextureDataInitializationFunction(GLint internalFormat) +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat) { - const InternalFormatInitializerMap &map = GetInternalFormatInitializerMap(); - InternalFormatInitializerMap::const_iterator iter = map.find(internalFormat); - if (iter != map.end()) + static const D3D11ES3FormatMap formatMap = BuildD3D11FormatMap(); + D3D11ES3FormatMap::const_iterator iter = formatMap.find(internalFormat); + if (iter != formatMap.end()) { return iter->second; } else { - UNREACHABLE(); - return NULL; + static const TextureFormat defaultInfo; + return defaultInfo; } } -struct D3D11VertexFormatInfo -{ - rx::VertexConversionType mConversionType; - DXGI_FORMAT mNativeFormat; - VertexCopyFunction mCopyFunction; - - D3D11VertexFormatInfo() - : mConversionType(VERTEX_CONVERT_NONE), - mNativeFormat(DXGI_FORMAT_UNKNOWN), - mCopyFunction(NULL) - {} - - D3D11VertexFormatInfo(VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction) - : mConversionType(conversionType), - mNativeFormat(nativeFormat), - mCopyFunction(copyFunction) - {} -}; +typedef std::map D3D11VertexFormatInfoMap; +typedef std::pair D3D11VertexFormatPair; -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, +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); - map->insert(D3D11VertexFormatPair(inputFormat, D3D11VertexFormatInfo(conversionType, nativeFormat, copyFunction))); + + 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, +static void AddIntegerVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inputType, GLuint componentCount, VertexConversionType conversionType, DXGI_FORMAT nativeFormat, VertexCopyFunction copyFunction) { gl::VertexFormat inputFormat(inputType, GL_FALSE, componentCount, true); - map->insert(D3D11VertexFormatPair(inputFormat, D3D11VertexFormatInfo(conversionType, nativeFormat, copyFunction))); + + VertexFormat info; + info.conversionType = conversionType; + info.nativeFormat = nativeFormat; + info.copyFunction = copyFunction; + + map->insert(D3D11VertexFormatPair(inputFormat, info)); } static D3D11VertexFormatInfoMap BuildD3D11VertexFormatInfoMap() @@ -1211,245 +908,165 @@ static D3D11VertexFormatInfoMap BuildD3D11VertexFormatInfoMap() // // GL_BYTE -- un-normalized - addVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, ©VertexData); - addVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, ©VertexData); - addVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, ©VertexData); - addVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, ©VertexData); + 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, ©VertexData); - addVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM, ©VertexData); - addVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM, ©VertexData); - addVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, ©VertexData); + 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, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, ©VertexData); + 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, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, ©VertexData); + 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, ©VertexData); - addVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, ©VertexData); - addVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, ©VertexData); - addVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, ©VertexData); + 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, ©VertexData); - addVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM, ©VertexData); - addVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, ©VertexData); - addVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, ©VertexData); + 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, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, ©VertexData); + 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, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, ©VertexData); + 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, ©VertexData); - addVertexFormatInfo(&map, GL_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, ©VertexData); - addVertexFormatInfo(&map, GL_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, ©VertexData); - addVertexFormatInfo(&map, GL_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, ©VertexData); + 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, ©ToFloatVertexData); - addVertexFormatInfo(&map, GL_INT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, ©ToFloatVertexData); - addVertexFormatInfo(&map, GL_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, ©ToFloatVertexData); - addVertexFormatInfo(&map, GL_INT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, ©ToFloatVertexData); + 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, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, ©VertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, ©VertexData); + 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, ©ToFloatVertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, ©ToFloatVertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, ©ToFloatVertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, ©ToFloatVertexData); + 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, ©FixedVertexData<1>); - addVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, ©FixedVertexData<2>); - addVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, ©FixedVertexData<3>); - addVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, ©FixedVertexData<4>); + 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, ©VertexData); - addVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, ©VertexData); - addVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT, ©VertexData); - addVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, ©VertexData); + 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, ©VertexData); - addVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, ©VertexData); - addVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, ©VertexData); - addVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, ©VertexData); + 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, ©PackedVertexData); - addVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, ©PackedVertexData); + 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, ©PackedVertexData); - addVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, ©PackedUnsignedVertexData); + 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, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT, ©VertexData); + 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, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT, ©VertexData); + 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, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT, ©VertexData); + 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, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT, ©VertexData); + 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, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, ©VertexData); + 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, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, ©VertexData); - addIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, ©VertexData); + 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, ©PackedVertexData); + 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, ©PackedUnsignedVertexData); + AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, &CopyNativeVertexData); return map; } -static bool GetD3D11VertexFormatInfo(const gl::VertexFormat &vertexFormat, D3D11VertexFormatInfo *outVertexFormatInfo) +const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat) { static const D3D11VertexFormatInfoMap vertexFormatMap = BuildD3D11VertexFormatInfoMap(); D3D11VertexFormatInfoMap::const_iterator iter = vertexFormatMap.find(vertexFormat); if (iter != vertexFormatMap.end()) - { - if (outVertexFormatInfo) - { - *outVertexFormatInfo = iter->second; - } - return true; - } - else - { - return false; - } -} - -VertexCopyFunction GetVertexCopyFunction(const gl::VertexFormat &vertexFormat) -{ - D3D11VertexFormatInfo vertexFormatInfo; - if (GetD3D11VertexFormatInfo(vertexFormat, &vertexFormatInfo)) - { - return vertexFormatInfo.mCopyFunction; - } - else - { - UNREACHABLE(); - return NULL; - } -} - -size_t GetVertexElementSize(const gl::VertexFormat &vertexFormat) -{ - D3D11VertexFormatInfo vertexFormatInfo; - if (GetD3D11VertexFormatInfo(vertexFormat, &vertexFormatInfo)) - { - // FIXME: should not need a client version, and is not a pixel! - return d3d11::GetFormatPixelBytes(vertexFormatInfo.mNativeFormat); - } - else - { - UNREACHABLE(); - return 0; - } -} - -rx::VertexConversionType GetVertexConversionType(const gl::VertexFormat &vertexFormat) -{ - D3D11VertexFormatInfo vertexFormatInfo; - if (GetD3D11VertexFormatInfo(vertexFormat, &vertexFormatInfo)) - { - return vertexFormatInfo.mConversionType; - } - else - { - UNREACHABLE(); - return VERTEX_CONVERT_NONE; - } -} - -DXGI_FORMAT GetNativeVertexFormat(const gl::VertexFormat &vertexFormat) -{ - D3D11VertexFormatInfo vertexFormatInfo; - if (GetD3D11VertexFormatInfo(vertexFormat, &vertexFormatInfo)) - { - return vertexFormatInfo.mNativeFormat; - } - else - { - UNREACHABLE(); - return DXGI_FORMAT_UNKNOWN; - } -} - -} - -namespace d3d11_gl -{ - -GLenum GetInternalFormat(DXGI_FORMAT format) -{ - const DXGIToESFormatMap &formatMap = GetDXGIToESFormatMap(); - DXGIToESFormatMap::const_iterator iter = formatMap.find(format); - if (iter != formatMap.end()) { return iter->second; } else { - UNREACHABLE(); - return GL_NONE; + 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 index d77fccfe9c..ea11aaa74c 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h @@ -12,65 +12,70 @@ #include "libGLESv2/formatutils.h" +#include + namespace rx { -class Renderer; - namespace d3d11 { -typedef std::set DXGIFormatSet; +typedef std::map, ColorCopyFunction> FastCopyFunctionMap; -MipGenerationFunction GetMipGenerationFunction(DXGI_FORMAT format); -LoadImageFunction GetImageLoadFunction(GLenum internalFormat, GLenum type); +struct DXGIFormat +{ + DXGIFormat(); -GLuint GetFormatPixelBytes(DXGI_FORMAT format); -GLuint GetBlockWidth(DXGI_FORMAT format); -GLuint GetBlockHeight(DXGI_FORMAT format); -GLenum GetComponentType(DXGI_FORMAT format); + GLuint pixelBytes; + GLuint blockWidth; + GLuint blockHeight; -GLuint GetDepthBits(DXGI_FORMAT format); -GLuint GetDepthOffset(DXGI_FORMAT format); -GLuint GetStencilBits(DXGI_FORMAT format); -GLuint GetStencilOffset(DXGI_FORMAT format); + GLuint depthBits; + GLuint depthOffset; + GLuint stencilBits; + GLuint stencilOffset; -void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); + GLenum internalFormat; + GLenum componentType; -const DXGIFormatSet &GetAllUsedDXGIFormats(); + MipGenerationFunction mipGenerationFunction; + ColorReadFunction colorReadFunction; -ColorReadFunction GetColorReadFunction(DXGI_FORMAT format); -ColorCopyFunction GetFastCopyFunction(DXGI_FORMAT sourceFormat, GLenum destFormat, GLenum destType); + FastCopyFunctionMap fastCopyFunctions; + ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const; +}; +const DXGIFormat &GetDXGIFormatInfo(DXGI_FORMAT format); -} - -namespace gl_d3d11 +struct TextureFormat { + TextureFormat(); -DXGI_FORMAT GetTexFormat(GLenum internalFormat); -DXGI_FORMAT GetSRVFormat(GLenum internalFormat); -DXGI_FORMAT GetRTVFormat(GLenum internalFormat); -DXGI_FORMAT GetDSVFormat(GLenum internalFormat); -DXGI_FORMAT GetRenderableFormat(GLenum internalFormat); - -DXGI_FORMAT GetSwizzleTexFormat(GLint internalFormat); -DXGI_FORMAT GetSwizzleSRVFormat(GLint internalFormat); -DXGI_FORMAT GetSwizzleRTVFormat(GLint internalFormat); + DXGI_FORMAT texFormat; + DXGI_FORMAT srvFormat; + DXGI_FORMAT rtvFormat; + DXGI_FORMAT dsvFormat; + DXGI_FORMAT renderFormat; -bool RequiresTextureDataInitialization(GLint internalFormat); -InitializeTextureDataFunction GetTextureDataInitializationFunction(GLint internalFormat); + DXGI_FORMAT swizzleTexFormat; + DXGI_FORMAT swizzleSRVFormat; + DXGI_FORMAT swizzleRTVFormat; -VertexCopyFunction GetVertexCopyFunction(const gl::VertexFormat &vertexFormat); -size_t GetVertexElementSize(const gl::VertexFormat &vertexFormat); -VertexConversionType GetVertexConversionType(const gl::VertexFormat &vertexFormat); -DXGI_FORMAT GetNativeVertexFormat(const gl::VertexFormat &vertexFormat); + InitializeTextureDataFunction dataInitializerFunction; -} + typedef std::map LoadFunctionMap; + LoadFunctionMap loadFunctions; +}; +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat); -namespace d3d11_gl +struct VertexFormat { + VertexFormat(); -GLenum GetInternalFormat(DXGI_FORMAT format); + VertexConversionType conversionType; + DXGI_FORMAT nativeFormat; + VertexCopyFunction copyFunction; +}; +const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat); } 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 d914a8201b..2af97e73f0 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 @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -10,8 +9,14 @@ #include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" #include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.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 @@ -21,6 +26,12 @@ #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 @@ -45,6 +56,48 @@ #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 +#ifndef D3D11_VS_OUTPUT_REGISTER_COUNT +# define D3D11_VS_OUTPUT_REGISTER_COUNT 32 +#endif namespace rx { @@ -258,16 +311,13 @@ static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, ID3D11De { gl::TextureCaps textureCaps; - DXGI_FORMAT textureFormat = gl_d3d11::GetTexFormat(internalFormat); - DXGI_FORMAT srvFormat = gl_d3d11::GetSRVFormat(internalFormat); - DXGI_FORMAT rtvFormat = gl_d3d11::GetRTVFormat(internalFormat); - DXGI_FORMAT dsvFormat = gl_d3d11::GetDSVFormat(internalFormat); - DXGI_FORMAT renderFormat = gl_d3d11::GetRenderableFormat(internalFormat); + const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat); UINT formatSupport; - if (SUCCEEDED(device->CheckFormatSupport(textureFormat, &formatSupport))) + if (SUCCEEDED(device->CheckFormatSupport(formatInfo.texFormat, &formatSupport))) { - if (gl::GetDepthBits(internalFormat) > 0 || gl::GetStencilBits(internalFormat) > 0) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0); } @@ -279,13 +329,13 @@ static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, ID3D11De } } - if (SUCCEEDED(device->CheckFormatSupport(renderFormat, &formatSupport)) && + 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(renderFormat, sampleCount, &qualityCount)) && + if (SUCCEEDED(device->CheckMultisampleQualityLevels(formatInfo.renderFormat, sampleCount, &qualityCount)) && qualityCount > 0) { textureCaps.sampleCounts.insert(sampleCount); @@ -293,11 +343,11 @@ static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, ID3D11De } } - textureCaps.filterable = SUCCEEDED(device->CheckFormatSupport(srvFormat, &formatSupport)) && + textureCaps.filterable = SUCCEEDED(device->CheckFormatSupport(formatInfo.srvFormat, &formatSupport)) && ((formatSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)) != 0; - textureCaps.renderable = (SUCCEEDED(device->CheckFormatSupport(rtvFormat, &formatSupport)) && + textureCaps.renderable = (SUCCEEDED(device->CheckFormatSupport(formatInfo.rtvFormat, &formatSupport)) && ((formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) != 0) || - (SUCCEEDED(device->CheckFormatSupport(dsvFormat, &formatSupport)) && + (SUCCEEDED(device->CheckFormatSupport(formatInfo.dsvFormat, &formatSupport)) && ((formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL) != 0)); return textureCaps; @@ -317,7 +367,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; } @@ -441,9 +491,8 @@ static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel #endif case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; - // FIXME(geofflang): Work around NVIDIA driver bug by repacking buffers case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return 1; /* D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT; */ + 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: @@ -554,13 +603,412 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) } } +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 _MSC_VER >= 1700 + 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 _MSC_VER >= 1700 + 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 _MSC_VER >= 1700 + 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 _MSC_VER >= 1700 + 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 _MSC_VER >= 1700 + 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 _MSC_VER >= 1700 + 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 _MSC_VER >= 1700 + 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 _MSC_VER >= 1700 + 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 _MSC_VER >= 1700 + 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 _MSC_VER >= 1700 + 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 _MSC_VER >= 1700 + 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 _MSC_VER >= 1700 + 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 _MSC_VER >= 1700 + 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 _MSC_VER >= 1700 + 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 _MSC_VER >= 1700 + 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 GetMaximumStreamOutputInterleavedComponenets(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if _MSC_VER >= 1700 + 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 GetMaximumStreamOutputSeparateCompeonents(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { +#if _MSC_VER >= 1700 + case D3D_FEATURE_LEVEL_11_1: +#endif + case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponenets(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(); @@ -595,6 +1043,54 @@ void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *text 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 = GetMaximumStreamOutputInterleavedComponenets(featureLevel); + caps->maxTransformFeedbackSeparateAttributes = GetMaximumStreamOutputBuffers(featureLevel); + caps->maxTransformFeedbackSeparateComponents = GetMaximumStreamOutputSeparateCompeonents(featureLevel); + // GL extension support extensions->setTextureExtensionSupport(*textureCapsMap); extensions->elementIndexUint = true; @@ -617,6 +1113,7 @@ void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *text extensions->blendMinMax = true; extensions->framebufferBlit = true; extensions->framebufferMultisample = true; + extensions->maxSamples = maxSamples; extensions->instancedArrays = GetInstancingSupport(featureLevel); extensions->packReverseRowOrder = true; extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel); @@ -631,12 +1128,33 @@ void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *text 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) { - InitializeTextureDataFunction initializeFunc = gl_d3d11::GetTextureDataInitializationFunction(internalFormat); - DXGI_FORMAT dxgiFormat = gl_d3d11::GetTexFormat(internalFormat); + 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); @@ -647,11 +1165,11 @@ void GenerateInitialTextureData(GLint internalFormat, GLuint width, GLuint heigh unsigned int mipHeight = std::max(height >> i, 1U); unsigned int mipDepth = std::max(depth >> i, 1U); - unsigned int rowWidth = d3d11::GetFormatPixelBytes(dxgiFormat) * mipWidth; + unsigned int rowWidth = dxgiFormatInfo.pixelBytes * mipWidth; unsigned int imageSize = rowWidth * height; outData->at(i).resize(rowWidth * mipHeight * mipDepth); - initializeFunc(mipWidth, mipHeight, mipDepth, outData->at(i).data(), rowWidth, imageSize); + d3dFormatInfo.dataInitializerFunction(mipWidth, mipHeight, mipDepth, outData->at(i).data(), rowWidth, imageSize); outSubresourceData->at(i).pSysMem = outData->at(i).data(); outSubresourceData->at(i).SysMemPitch = rowWidth; @@ -687,6 +1205,12 @@ HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) #endif } +RenderTarget11 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment) +{ + RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment); + return RenderTarget11::makeRenderTarget11(renderTarget); +} + } } 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 index 4de9bfa86d..4c05eb9256 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h @@ -13,8 +13,16 @@ #include "libGLESv2/angletypes.h" #include "libGLESv2/Caps.h" +#include + +namespace gl +{ +class FramebufferAttachment; +} + namespace rx { +class RenderTarget11; namespace gl_d3d11 { @@ -47,6 +55,8 @@ void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *text 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); @@ -166,6 +176,8 @@ inline void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBu context->Unmap(constantBuffer, 0); } +RenderTarget11 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment); + } } 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 f486e5a4cc..f061a32c52 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -8,8 +7,6 @@ // Blit9.cpp: Surface copy utility class. #include "libGLESv2/renderer/d3d/d3d9/Blit9.h" - -#include "libGLESv2/main.h" #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" #include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" @@ -17,9 +14,11 @@ #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" @@ -209,7 +208,7 @@ bool Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) return true; } -bool Blit9::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) +bool Blit9::copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) { RenderTarget9 *renderTarget = NULL; IDirect3DSurface9 *source = NULL; @@ -217,9 +216,9 @@ bool Blit9::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum de if (colorbuffer) { - renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); + renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer); } - + if (renderTarget) { source = renderTarget->getSurface(); @@ -231,10 +230,10 @@ bool Blit9::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum de return gl::error(GL_OUT_OF_MEMORY, false); } - TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); + TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); IDirect3DSurface9 *destSurface = storage9->getSurfaceLevel(level, true); bool result = false; - + if (destSurface) { result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); @@ -245,7 +244,7 @@ bool Blit9::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum de return result; } -bool Blit9::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) +bool Blit9::copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) { RenderTarget9 *renderTarget = NULL; IDirect3DSurface9 *source = NULL; @@ -253,9 +252,9 @@ bool Blit9::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum de if (colorbuffer) { - renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); + renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer); } - + if (renderTarget) { source = renderTarget->getSurface(); @@ -267,7 +266,7 @@ bool Blit9::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum de return gl::error(GL_OUT_OF_MEMORY, false); } - TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); + TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); IDirect3DSurface9 *destSurface = storage9->getCubeMapSurface(target, level, true); bool result = false; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h index 3635bca932..46a3ee1cf3 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h @@ -11,6 +11,8 @@ #include "common/angleutils.h" +#include + namespace gl { class Framebuffer; @@ -19,8 +21,7 @@ class Framebuffer; namespace rx { class Renderer9; -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; +class TextureStorage; class Blit9 { @@ -30,8 +31,8 @@ class Blit9 // Copy from source surface to dest surface. // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) - bool copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); - bool copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); + bool copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level); + bool 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) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp index 347bde0c65..c02db515a2 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright 2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -8,8 +7,8 @@ // Buffer9.cpp Defines the Buffer9 class. #include "libGLESv2/renderer/d3d/d3d9/Buffer9.h" -#include "libGLESv2/main.h" #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/main.h" namespace rx { @@ -18,13 +17,11 @@ Buffer9::Buffer9(rx::Renderer9 *renderer) : BufferD3D(), mRenderer(renderer), mSize(0) -{ - -} +{} Buffer9::~Buffer9() { - + mSize = 0; } Buffer9 *Buffer9::makeBuffer9(BufferImpl *buffer) @@ -33,18 +30,13 @@ Buffer9 *Buffer9::makeBuffer9(BufferImpl *buffer) return static_cast(buffer); } -void Buffer9::clear() -{ - mSize = 0; -} - -void Buffer9::setData(const void* data, size_t size, GLenum usage) +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); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer."); } } @@ -54,14 +46,14 @@ void Buffer9::setData(const void* data, size_t size, GLenum usage) memcpy(mMemory.data(), data, size); } - mIndexRangeCache.clear(); - invalidateStaticData(); if (usage == GL_STATIC_DRAW) { initializeStaticData(); } + + return gl::Error(GL_NO_ERROR); } void *Buffer9::getData() @@ -69,13 +61,13 @@ void *Buffer9::getData() return mMemory.data(); } -void Buffer9::setSubData(const void* data, size_t size, size_t offset) +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); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal buffer."); } } @@ -85,32 +77,35 @@ void Buffer9::setSubData(const void* data, size_t size, size_t offset) memcpy(mMemory.data() + offset, data, size); } - mIndexRangeCache.invalidateRange(offset, size); - invalidateStaticData(); + + return gl::Error(GL_NO_ERROR); } -void Buffer9::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +gl::Error Buffer9::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) { + // Note: this method is currently unreachable Buffer9* sourceBuffer = makeBuffer9(source); - if (sourceBuffer) - { - memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size); - } + ASSERT(sourceBuffer); + + memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size); invalidateStaticData(); + + return gl::Error(GL_NO_ERROR); } -// We do not suppot buffer mapping in D3D9 -GLvoid* Buffer9::map(size_t offset, size_t length, GLbitfield access) +// We do not support buffer mapping in D3D9 +gl::Error Buffer9::map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) { UNREACHABLE(); - return NULL; + return gl::Error(GL_INVALID_OPERATION); } -void Buffer9::unmap() +gl::Error Buffer9::unmap() { UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); } void Buffer9::markTransformFeedbackUsage() diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h index ec25ec30c9..e78182f905 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h @@ -27,17 +27,16 @@ class Buffer9 : public BufferD3D // BufferD3D implementation virtual size_t getSize() const { return mSize; } - virtual void clear(); virtual bool supportsDirectBinding() const { return false; } virtual Renderer* getRenderer(); // BufferImpl implementation - virtual void setData(const void* data, size_t size, GLenum usage); + virtual gl::Error setData(const void* data, size_t size, GLenum usage); virtual void *getData(); - virtual void setSubData(const void* data, size_t size, size_t offset); - virtual void copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size); - virtual GLvoid* map(size_t offset, size_t length, GLbitfield access); - virtual void unmap(); + 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: diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp index d2437cadf3..e352a5f50a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -8,9 +7,9 @@ // Fence9.cpp: Defines the rx::Fence9 class. #include "libGLESv2/renderer/d3d/d3d9/Fence9.h" -#include "libGLESv2/main.h" #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/main.h" namespace rx { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp index e237c3b6e1..18383fba78 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp @@ -1,5 +1,3 @@ - -#include "precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -10,17 +8,16 @@ // 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 "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" namespace rx { @@ -53,8 +50,8 @@ void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sour ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width); ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height); - MipGenerationFunction mipFunction = d3d9::GetMipGenerationFunction(sourceDesc.Format); - ASSERT(mipFunction != NULL); + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(sourceDesc.Format); + ASSERT(d3dFormatInfo.mipGenerationFunction != NULL); D3DLOCKED_RECT sourceLocked = {0}; result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY); @@ -69,8 +66,8 @@ void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sour if (sourceData && destData) { - mipFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, sourceLocked.Pitch, 0, - destData, destLocked.Pitch, 0); + d3dFormatInfo.mipGenerationFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, sourceLocked.Pitch, 0, + destData, destLocked.Pitch, 0); } destSurface->UnlockRect(); @@ -99,22 +96,23 @@ void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *so { D3DLOCKED_RECT sourceLock = {0}; D3DLOCKED_RECT destLock = {0}; - + source->LockRect(&sourceLock, NULL, 0); dest->LockRect(&destLock, NULL, 0); - + if (sourceLock.pBits && destLock.pBits) { D3DSURFACE_DESC desc; source->GetDesc(&desc); - int blockHeight = d3d9::GetBlockHeight(desc.Format); - int rows = desc.Height / blockHeight; + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format); + unsigned int rows = desc.Height / d3dFormatInfo.blockHeight; - int bytes = d3d9::GetBlockSize(desc.Format, desc.Width, blockHeight); - ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch); + unsigned int bytes = d3d9::ComputeBlockSize(desc.Format, desc.Width, d3dFormatInfo.blockHeight); + ASSERT(bytes <= static_cast(sourceLock.Pitch) && + bytes <= static_cast(destLock.Pitch)); - for(int i = 0; i < rows; i++) + for(unsigned int i = 0; i < rows; i++) { memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes); } @@ -147,12 +145,14 @@ bool Image9::redefine(rx::Renderer *renderer, GLenum target, GLenum internalform mInternalFormat = internalformat; // compute the d3d format that will be used - mD3DFormat = gl_d3d9::GetTextureFormat(internalformat); - mActualFormat = d3d9_gl::GetInternalFormat(mD3DFormat); - mRenderable = gl_d3d9::GetRenderFormat(internalformat) != D3DFMT_UNKNOWN; + 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 = gl_d3d9::RequiresTextureDataInitialization(mInternalFormat); + mDirty = (d3d9FormatInfo.dataInitializerFunction != NULL); return true; } @@ -194,10 +194,9 @@ void Image9::createSurface() newTexture->GetSurfaceLevel(levelToFetch, &newSurface); SafeRelease(newTexture); - if (gl_d3d9::RequiresTextureDataInitialization(mInternalFormat)) + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); + if (d3dFormatInfo.dataInitializerFunction != NULL) { - InitializeTextureDataFunction initializeFunc = gl_d3d9::GetTextureDataInitializationFunction(mInternalFormat); - RECT entireRect; entireRect.left = 0; entireRect.right = mWidth; @@ -208,7 +207,8 @@ void Image9::createSurface() result = newSurface->LockRect(&lockedRect, &entireRect, 0); ASSERT(SUCCEEDED(result)); - initializeFunc(mWidth, mHeight, 1, reinterpret_cast(lockedRect.pBits), lockedRect.Pitch, 0); + d3dFormatInfo.dataInitializerFunction(mWidth, mHeight, 1, reinterpret_cast(lockedRect.pBits), + lockedRect.Pitch, 0); result = newSurface->UnlockRect(); ASSERT(SUCCEEDED(result)); @@ -260,7 +260,7 @@ 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 || gl_d3d9::RequiresTextureDataInitialization(mInternalFormat)) && mDirty; + return (mSurface || d3d9::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL) && mDirty; } IDirect3DSurface9 *Image9::getSurface() @@ -270,15 +270,15 @@ IDirect3DSurface9 *Image9::getSurface() return mSurface; } -void Image9::setManagedSurface(TextureStorageInterface2D *storage, int level) +void Image9::setManagedSurface2D(TextureStorage *storage, int level) { - TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); + TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); setManagedSurface(storage9->getSurfaceLevel(level, false)); } -void Image9::setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level) +void Image9::setManagedSurfaceCube(TextureStorage *storage, int face, int level) { - TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); + TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); setManagedSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false)); } @@ -301,28 +301,28 @@ void Image9::setManagedSurface(IDirect3DSurface9 *surface) } } -bool Image9::copyToStorage(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +bool Image9::copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) { ASSERT(getSurface() != NULL); - TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); + TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage); return copyToSurface(storage9->getSurfaceLevel(level, true), xoffset, yoffset, width, height); } -bool Image9::copyToStorage(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +bool Image9::copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) { ASSERT(getSurface() != NULL); - TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); + TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage); return copyToSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true), xoffset, yoffset, width, height); } -bool Image9::copyToStorage(TextureStorageInterface3D *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) +bool Image9::copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) { // 3D textures are not supported by the D3D9 backend. UNREACHABLE(); return false; } -bool Image9::copyToStorage(TextureStorageInterface2DArray *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height) +bool Image9::copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height) { // 2D array textures are not supported by the D3D9 backend. UNREACHABLE(); @@ -368,7 +368,7 @@ bool Image9::copyToSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint } else { - // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools + // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point); UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); @@ -387,10 +387,11 @@ void Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width // 3D textures are not supported by the D3D9 backend. ASSERT(zoffset == 0 && depth == 1); - GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, type, width, unpackAlignment); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat); + GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment); - LoadImageFunction loadFunction = d3d9::GetImageLoadFunction(mInternalFormat); - ASSERT(loadFunction != NULL); + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); + ASSERT(d3dFormatInfo.loadFunction != NULL); RECT lockRect = { @@ -405,9 +406,9 @@ void Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width return; } - loadFunction(width, height, depth, - reinterpret_cast(input), inputRowPitch, 0, - reinterpret_cast(locked.pBits), locked.Pitch, 0); + d3dFormatInfo.loadFunction(width, height, depth, + reinterpret_cast(input), inputRowPitch, 0, + reinterpret_cast(locked.pBits), locked.Pitch, 0); unlock(); } @@ -418,14 +419,16 @@ void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLs // 3D textures are not supported by the D3D9 backend. ASSERT(zoffset == 0 && depth == 1); - GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, GL_UNSIGNED_BYTE, width, 1); - GLsizei inputDepthPitch = gl::GetDepthPitch(mInternalFormat, GL_UNSIGNED_BYTE, width, height, 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); - ASSERT(xoffset % d3d9::GetBlockWidth(mD3DFormat) == 0); - ASSERT(yoffset % d3d9::GetBlockHeight(mD3DFormat) == 0); + const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat); - LoadImageFunction loadFunction = d3d9::GetImageLoadFunction(mInternalFormat); - ASSERT(loadFunction != NULL); + ASSERT(xoffset % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0); + ASSERT(yoffset % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0); + + ASSERT(d3d9FormatInfo.loadFunction != NULL); RECT lockRect = { @@ -440,9 +443,9 @@ void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLs return; } - loadFunction(width, height, depth, - reinterpret_cast(input), inputRowPitch, inputDepthPitch, - reinterpret_cast(locked.pBits), locked.Pitch, 0); + d3d9FormatInfo.loadFunction(width, height, depth, + reinterpret_cast(input), inputRowPitch, inputDepthPitch, + reinterpret_cast(locked.pBits), locked.Pitch, 0); unlock(); } @@ -459,9 +462,9 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, if (colorbuffer) { - renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); + renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer); } - + if (renderTarget) { surface = renderTarget->getSurface(); @@ -478,7 +481,7 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, 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)) @@ -514,7 +517,7 @@ void Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, D3DLOCKED_RECT destLock = {0}; result = lock(&destLock, &destRect); - + if (FAILED(result)) { ERR("Failed to lock the destination surface (rectangle might be invalid)."); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h index 2d1536f24b..08d8ee3545 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h @@ -22,8 +22,6 @@ namespace rx { class Renderer; class Renderer9; -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; class Image9 : public ImageD3D { @@ -44,12 +42,12 @@ class Image9 : public ImageD3D virtual bool isDirty() const; IDirect3DSurface9 *getSurface(); - virtual void setManagedSurface(TextureStorageInterface2D *storage, int level); - virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level); - virtual bool copyToStorage(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - virtual bool copyToStorage(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - virtual bool copyToStorage(TextureStorageInterface3D *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); - virtual bool copyToStorage(TextureStorageInterface2DArray *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height); + virtual void setManagedSurface2D(TextureStorage *storage, int level); + virtual void setManagedSurfaceCube(TextureStorage *storage, int face, int level); + virtual bool copyToStorage2D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + virtual bool copyToStorageCube(TextureStorage *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + virtual bool copyToStorage3D(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); + virtual bool copyToStorage2DArray(TextureStorage *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height); virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLint unpackAlignment, GLenum type, const void *input); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp index 472e6981a8..1c51b9e985 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -26,7 +25,7 @@ IndexBuffer9::~IndexBuffer9() SafeRelease(mIndexBuffer); } -bool IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) +gl::Error IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) { SafeRelease(mIndexBuffer); @@ -34,28 +33,17 @@ bool IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dy if (bufferSize > 0) { - D3DFORMAT format; + D3DFORMAT format = D3DFMT_UNKNOWN; if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE) { format = D3DFMT_INDEX16; } else if (indexType == GL_UNSIGNED_INT) { - if (mRenderer->getRendererExtensions().elementIndexUint) - { - format = D3DFMT_INDEX32; - } - else - { - ERR("Attempted to create a 32-bit index buffer but renderer does not support 32-bit indices."); - return false; - } - } - else - { - ERR("Invalid index type %u.", indexType); - return false; + ASSERT(mRenderer->getRendererExtensions().elementIndexUint); + format = D3DFMT_INDEX32; } + else UNREACHABLE(); DWORD usageFlags = D3DUSAGE_WRITEONLY; if (dynamic) @@ -66,8 +54,7 @@ bool IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dy HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer); if (FAILED(result)) { - ERR("Failed to create an index buffer of size %u, result: 0x%08x.", mBufferSize, result); - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal index buffer of size, %lu.", bufferSize); } } @@ -75,7 +62,7 @@ bool IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dy mIndexType = indexType; mDynamic = dynamic; - return true; + return gl::Error(GL_NO_ERROR); } IndexBuffer9 *IndexBuffer9::makeIndexBuffer9(IndexBuffer *indexBuffer) @@ -84,48 +71,40 @@ IndexBuffer9 *IndexBuffer9::makeIndexBuffer9(IndexBuffer *indexBuffer) return static_cast(indexBuffer); } -bool IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) +gl::Error IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) { - if (mIndexBuffer) + if (!mIndexBuffer) { - DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0; + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + } - void *mapPtr = NULL; - HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags); - if (FAILED(result)) - { - ERR("Index buffer lock failed with error 0x%08x", result); - return false; - } + DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0; - *outMappedMemory = mapPtr; - return true; - } - else + void *mapPtr = NULL; + HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags); + if (FAILED(result)) { - ERR("Index buffer not initialized."); - return false; + 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); } -bool IndexBuffer9::unmapBuffer() +gl::Error IndexBuffer9::unmapBuffer() { - if (mIndexBuffer) + if (!mIndexBuffer) { - HRESULT result = mIndexBuffer->Unlock(); - if (FAILED(result)) - { - ERR("Index buffer unlock failed with error 0x%08x", result); - return false; - } - - return true; + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); } - else + + HRESULT result = mIndexBuffer->Unlock(); + if (FAILED(result)) { - ERR("Index buffer not initialized."); - return false; + 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 @@ -138,7 +117,7 @@ unsigned int IndexBuffer9::getBufferSize() const return mBufferSize; } -bool IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType) +gl::Error IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType) { if (bufferSize > mBufferSize || indexType != mIndexType) { @@ -146,38 +125,33 @@ bool IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType) } else { - return true; + return gl::Error(GL_NO_ERROR); } } -bool IndexBuffer9::discard() +gl::Error IndexBuffer9::discard() { - if (mIndexBuffer) + if (!mIndexBuffer) { - void *dummy; - HRESULT result; - - result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); - if (FAILED(result)) - { - ERR("Discard lock failed with error 0x%08x", result); - return false; - } + return gl::Error(GL_OUT_OF_MEMORY, "Internal index buffer is not initialized."); + } - result = mIndexBuffer->Unlock(); - if (FAILED(result)) - { - ERR("Discard unlock failed with error 0x%08x", result); - return false; - } + void *dummy; + HRESULT result; - return true; + 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); } - else + + result = mIndexBuffer->Unlock(); + if (FAILED(result)) { - ERR("Index buffer not initialized."); - return false; + 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 @@ -196,4 +170,4 @@ IDirect3DIndexBuffer9 * IndexBuffer9::getBuffer() const return mIndexBuffer; } -} \ No newline at end of file +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h index cfc20e1c64..d0970d6ac5 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h @@ -21,18 +21,18 @@ class IndexBuffer9 : public IndexBuffer explicit IndexBuffer9(Renderer9 *const renderer); virtual ~IndexBuffer9(); - virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); + virtual gl::Error initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); static IndexBuffer9 *makeIndexBuffer9(IndexBuffer *indexBuffer); - virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); - virtual bool unmapBuffer(); + virtual 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 bool setSize(unsigned int bufferSize, GLenum indexType); + virtual gl::Error setSize(unsigned int bufferSize, GLenum indexType); - virtual bool discard(); + virtual gl::Error discard(); D3DFORMAT getIndexFormat() const; IDirect3DIndexBuffer9 *getBuffer() const; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp index 3c6f1d0d43..815fc01a9b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -7,19 +6,22 @@ // Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl. - #include "libGLESv2/renderer/d3d/d3d9/Query9.h" -#include "libGLESv2/main.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(rx::Renderer9 *renderer, GLenum type) : QueryImpl(type) +Query9::Query9(rx::Renderer9 *renderer, GLenum type) + : QueryImpl(type), + mResult(GL_FALSE), + mQueryFinished(false), + mRenderer(renderer), + mQuery(NULL) { - mRenderer = renderer; - mQuery = NULL; } Query9::~Query9() @@ -27,73 +29,91 @@ Query9::~Query9() SafeRelease(mQuery); } -void Query9::begin() +gl::Error Query9::begin() { if (mQuery == NULL) { - if (FAILED(mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery))) + HRESULT result = mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery); + if (FAILED(result)) { - return gl::error(GL_OUT_OF_MEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Internal query creation failed, result: 0x%X.", result); } } HRESULT result = mQuery->Issue(D3DISSUE_BEGIN); - UNUSED_ASSERTION_VARIABLE(result); 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); } -void Query9::end() +gl::Error Query9::end() { ASSERT(mQuery); HRESULT result = mQuery->Issue(D3DISSUE_END); - UNUSED_ASSERTION_VARIABLE(result); ASSERT(SUCCEEDED(result)); + if (FAILED(result)) + { + return gl::Error(GL_OUT_OF_MEMORY, "Failed to end internal query, result: 0x%X.", result); + } - mStatus = GL_FALSE; + mQueryFinished = false; mResult = GL_FALSE; + + return gl::Error(GL_NO_ERROR); } -GLuint Query9::getResult() +gl::Error Query9::getResult(GLuint *params) { - if (mQuery != NULL) + while (!mQueryFinished) { - while (!testQuery()) + gl::Error error = testQuery(); + if (error.isError()) + { + return error; + } + + if (!mQueryFinished) { Sleep(0); - // explicitly check for device loss - // some drivers seem to return S_FALSE even if the device is lost - // instead of D3DERR_DEVICELOST like they should - if (mRenderer->testDeviceLost(true)) - { - return gl::error(GL_OUT_OF_MEMORY, 0); - } } } - return mResult; + ASSERT(mQueryFinished); + *params = mResult; + + return gl::Error(GL_NO_ERROR); } -GLboolean Query9::isResultAvailable() +gl::Error Query9::isResultAvailable(GLuint *available) { - if (mQuery != NULL) + gl::Error error = testQuery(); + if (error.isError()) { - testQuery(); + return error; } - return mStatus; + *available = (mQueryFinished ? GL_TRUE : GL_FALSE); + + return gl::Error(GL_NO_ERROR); } -GLboolean Query9::testQuery() +gl::Error Query9::testQuery() { - if (mQuery != NULL && mStatus != GL_TRUE) + if (!mQueryFinished) { + ASSERT(mQuery); + DWORD numPixels = 0; HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH); if (hres == S_OK) { - mStatus = GL_TRUE; + mQueryFinished = true; switch (getType()) { @@ -101,25 +121,24 @@ GLboolean Query9::testQuery() case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; break; + default: - ASSERT(false); + UNREACHABLE(); + break; } } else if (d3d9::isDeviceLostError(hres)) { mRenderer->notifyDeviceLost(); - return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); + 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 mStatus; } - return GL_TRUE; // prevent blocking when query is null -} - -bool Query9::isStarted() const -{ - return (mQuery != NULL); + 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 index 62906230c4..513e0ba6fd 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h @@ -21,16 +21,18 @@ class Query9 : public QueryImpl Query9(rx::Renderer9 *renderer, GLenum type); virtual ~Query9(); - virtual void begin(); - virtual void end(); - virtual GLuint getResult(); - virtual GLboolean isResultAvailable(); - virtual bool isStarted() const; + 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); - GLboolean testQuery(); + gl::Error testQuery(); + + GLuint mResult; + bool mQueryFinished; rx::Renderer9 *mRenderer; IDirect3DQuery9 *mQuery; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp index 49bd9b4000..13321ac8cd 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -10,7 +9,6 @@ #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/formatutils9.h" #include "libGLESv2/main.h" @@ -33,8 +31,9 @@ RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface) mHeight = description.Height; mDepth = 1; - mInternalFormat = d3d9_gl::GetInternalFormat(description.Format); - mActualFormat = d3d9_gl::GetInternalFormat(description.Format); + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(description.Format); + mInternalFormat = d3dFormatInfo.internalFormat; + mActualFormat = d3dFormatInfo.internalFormat; mSamples = d3d9_gl::GetSamplesCount(description.MultiSampleType); } } @@ -44,15 +43,11 @@ RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, mRenderer = Renderer9::makeRenderer9(renderer); mRenderTarget = NULL; - D3DFORMAT renderFormat = gl_d3d9::GetRenderFormat(internalFormat); - int supportedSamples = mRenderer->getNearestSupportedSamples(renderFormat, samples); + const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalFormat); + const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(d3d9FormatInfo.renderFormat); - if (supportedSamples == -1) - { - gl::error(GL_OUT_OF_MEMORY); - - return; - } + const gl::TextureCaps &textureCaps = mRenderer->getRendererTextureCaps().get(internalFormat); + GLuint supportedSamples = textureCaps.getNearestSamples(samples); HRESULT result = D3DERR_INVALIDCALL; @@ -62,18 +57,17 @@ RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, bool requiresInitialization = false; - if (gl::GetDepthBits(internalFormat) > 0 || - gl::GetStencilBits(internalFormat) > 0) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) { - result = device->CreateDepthStencilSurface(width, height, renderFormat, + result = device->CreateDepthStencilSurface(width, height, d3d9FormatInfo.renderFormat, gl_d3d9::GetMultisampleType(supportedSamples), 0, FALSE, &mRenderTarget, NULL); } else { - requiresInitialization = gl_d3d9::RequiresTextureDataInitialization(internalFormat); - - result = device->CreateRenderTarget(width, height, renderFormat, + requiresInitialization = (d3d9FormatInfo.dataInitializerFunction != NULL); + result = device->CreateRenderTarget(width, height, d3d9FormatInfo.renderFormat, gl_d3d9::GetMultisampleType(supportedSamples), 0, FALSE, &mRenderTarget, NULL); } @@ -105,7 +99,7 @@ RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, mDepth = 1; mInternalFormat = internalFormat; mSamples = supportedSamples; - mActualFormat = d3d9_gl::GetInternalFormat(renderFormat); + mActualFormat = d3dFormatInfo.internalFormat; } RenderTarget9::~RenderTarget9() 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 2c8a79f964..d63f9b8582 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -7,17 +6,6 @@ // Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer. -#include "common/utilities.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/renderer/d3d/IndexDataManager.h" -#include "libGLESv2/renderer/d3d/TextureD3D.h" #include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" @@ -33,11 +21,25 @@ #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/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/angletypes.h" #include "libEGL/Display.h" -#include "third_party/trace_event/trace_event.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 @@ -117,13 +119,12 @@ Renderer9::Renderer9(egl::Display *display, EGLNativeDisplayType hDc, EGLint req mDeviceLost = false; - mMaxSupportedSamples = 0; - mMaskedClearSavedState = NULL; mVertexDataManager = NULL; mIndexDataManager = NULL; mLineLoopIB = NULL; + mCountingIB = NULL; mMaxNullColorbufferLRU = 0; for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) @@ -155,6 +156,7 @@ Renderer9::~Renderer9() void Renderer9::release() { + releaseShaderCompiler(); releaseDeviceResources(); SafeRelease(mDevice); @@ -186,7 +188,6 @@ EGLint Renderer9::initialize() return EGL_NOT_INITIALIZED; } - TRACE_EVENT0("gpu", "GetModuleHandle_d3d9"); mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); if (mD3d9Module == NULL) @@ -203,14 +204,12 @@ EGLint Renderer9::initialize() // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) { - TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface"); ASSERT(mD3d9Ex); mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast(&mD3d9)); ASSERT(mD3d9); } else { - TRACE_EVENT0("gpu", "Direct3DCreate9"); mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); } @@ -229,7 +228,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); @@ -264,7 +262,6 @@ EGLint Renderer9::initialize() } { - TRACE_EVENT0("gpu", "GetAdapterIdentifier"); mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); } @@ -297,22 +294,10 @@ EGLint Renderer9::initialize() mMaxSwapInterval = std::max(mMaxSwapInterval, 4); } - mMaxSupportedSamples = 0; - - const d3d9::D3DFormatSet &d3d9Formats = d3d9::GetAllUsedD3DFormats(); - for (d3d9::D3DFormatSet::const_iterator i = d3d9Formats.begin(); i != d3d9Formats.end(); ++i) - { - TRACE_EVENT0("gpu", "getMultiSampleSupport"); - MultisampleSupportInfo support = getMultiSampleSupport(*i); - mMultiSampleSupport[*i] = support; - mMaxSupportedSamples = std::max(mMaxSupportedSamples, support.maxSupportedSamples); - } - 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); } @@ -324,7 +309,6 @@ EGLint Renderer9::initialize() behaviorFlags |= 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) @@ -334,7 +318,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)) @@ -346,13 +329,11 @@ EGLint Renderer9::initialize() 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); } @@ -369,8 +350,6 @@ EGLint Renderer9::initialize() initializeDevice(); - d3d9::InitializeVertexTranslations(this); - return EGL_SUCCESS; } @@ -392,6 +371,17 @@ void Renderer9::initializeDevice() 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; @@ -436,40 +426,24 @@ int Renderer9::generateConfigs(ConfigDesc **configDescList) for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) { - D3DFORMAT renderTargetFormat = RenderTargetFormats[formatIndex]; - - HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat); - - if (SUCCEEDED(result)) + 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++) { - D3DFORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; - HRESULT result = D3D_OK; - - if(depthStencilFormat != D3DFMT_UNKNOWN) - { - result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat); - } - - if (SUCCEEDED(result)) + const d3d9::D3DFormat &depthStencilFormatInfo = d3d9::GetD3DFormatInfo(DepthStencilFormats[depthStencilIndex]); + const gl::TextureCaps &depthStencilFormatCaps = getRendererTextureCaps().get(depthStencilFormatInfo.internalFormat); + if (depthStencilFormatCaps.renderable || DepthStencilFormats[depthStencilIndex] == D3DFMT_UNKNOWN) { - if(depthStencilFormat != D3DFMT_UNKNOWN) - { - result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat); - } - - if (SUCCEEDED(result)) - { - ConfigDesc newConfig; - newConfig.renderTargetFormat = d3d9_gl::GetInternalFormat(renderTargetFormat); - newConfig.depthStencilFormat = d3d9_gl::GetInternalFormat(depthStencilFormat); - newConfig.multiSample = 0; // FIXME: enumerate multi-sampling - newConfig.fastConfig = (currentDisplayMode.Format == renderTargetFormat); - newConfig.es3Capable = false; - - (*configDescList)[numConfigs++] = newConfig; - } + 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; } } } @@ -635,6 +609,11 @@ FenceImpl *Renderer9::createFence() return new Fence9(this); } +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. @@ -649,16 +628,17 @@ bool Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsi return false; } -void Renderer9::generateSwizzle(gl::Texture *texture) +gl::Error Renderer9::generateSwizzle(gl::Texture *texture) { // Swizzled textures are not available in ES2 or D3D9 UNREACHABLE(); + return gl::Error(GL_INVALID_OPERATION); } -void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) +gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) { - bool *forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates; - gl::SamplerState *appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates; + 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) { @@ -682,9 +662,11 @@ void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::Sampl forceSetSamplers[index] = false; appliedSamplers[index] = samplerState; + + return gl::Error(GL_NO_ERROR); } -void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture) +gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture) { int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; int d3dSampler = index + d3dSamplerOffset; @@ -692,14 +674,16 @@ void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture unsigned int serial = 0; bool forceSetTexture = false; - unsigned int *appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials; + std::vector &appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials; if (texture) { - TextureStorageInterface *texStorage = texture->getNativeTexture(); + TextureD3D* textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation()); + + TextureStorage *texStorage = textureImpl->getNativeTexture(); if (texStorage) { - TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage->getStorageInstance()); + TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage); d3dTexture = storage9->getBaseTexture(); } // If we get NULL back from getBaseTexture here, something went wrong @@ -707,7 +691,8 @@ void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture ASSERT(d3dTexture != NULL); serial = texture->getTextureSerial(); - forceSetTexture = texture->hasDirtyImages(); + forceSetTexture = textureImpl->hasDirtyImages(); + textureImpl->resetDirty(); } if (forceSetTexture || appliedSerials[index] != serial) @@ -716,15 +701,17 @@ void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture } appliedSerials[index] = serial; + + return gl::Error(GL_NO_ERROR); } -bool Renderer9::setUniformBuffers(const gl::Buffer* /*vertexUniformBuffers*/[], const gl::Buffer* /*fragmentUniformBuffers*/[]) +gl::Error Renderer9::setUniformBuffers(const gl::Buffer* /*vertexUniformBuffers*/[], const gl::Buffer* /*fragmentUniformBuffers*/[]) { // No effect in ES2/D3D9 - return true; + return gl::Error(GL_NO_ERROR); } -void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState) +gl::Error Renderer9::setRasterizerState(const gl::RasterizerState &rasterState) { bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0; @@ -760,10 +747,12 @@ void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState) } mForceSetRasterState = false; + + return gl::Error(GL_NO_ERROR); } -void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask) +gl::Error Renderer9::setBlendState(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; @@ -828,10 +817,11 @@ void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState // drawing is done. // http://code.google.com/p/angleproject/issues/detail?id=169 - DWORD colorMask = gl_d3d9::ConvertColorMask(gl::GetRedBits(internalFormat) > 0 && blendState.colorMaskRed, - gl::GetGreenBits(internalFormat) > 0 && blendState.colorMaskGreen, - gl::GetBlueBits(internalFormat) > 0 && blendState.colorMaskBlue, - gl::GetAlphaBits(internalFormat) > 0 && blendState.colorMaskAlpha); + 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. @@ -863,10 +853,12 @@ void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState } mForceSetBlendState = false; + + return gl::Error(GL_NO_ERROR); } -void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW) +gl::Error Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW) { bool depthStencilStateChanged = mForceSetDepthStencilState || memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0; @@ -955,6 +947,8 @@ void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilSt } mForceSetDepthStencilState = false; + + return gl::Error(GL_NO_ERROR); } void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) @@ -984,7 +978,7 @@ void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) mForceSetScissor = false; } -bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, +void Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, bool ignoreViewport) { gl::Rectangle actualViewport = viewport; @@ -1008,11 +1002,6 @@ bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zF dxViewport.MinZ = actualZNear; dxViewport.MaxZ = actualZFar; - if (dxViewport.Width <= 0 || dxViewport.Height <= 0) - { - return false; // Nothing to render - } - float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f); bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || @@ -1065,7 +1054,6 @@ bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zF } mForceSetViewport = false; - return true; } bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count) @@ -1133,7 +1121,7 @@ gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachme } gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(0, new gl::Colorbuffer(this, width, height, GL_NONE, 0)); - gl::RenderbufferAttachment *nullbuffer = new gl::RenderbufferAttachment(nullRenderbuffer); + gl::RenderbufferAttachment *nullbuffer = new gl::RenderbufferAttachment(GL_NONE, nullRenderbuffer); // add nullbuffer to the cache NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0]; @@ -1154,7 +1142,7 @@ gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachme return nullbuffer; } -bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) +gl::Error Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) { // if there is no color attachment we must synthesize a NULL colorattachment // to keep the D3D runtime happy. This should only be possible if depth texturing. @@ -1165,27 +1153,25 @@ bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) } if (!attachment) { - ERR("unable to locate renderbuffer for FBO."); - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Unable to locate renderbuffer for FBO."); } bool renderTargetChanged = false; - unsigned int renderTargetSerial = attachment->getSerial(); + unsigned int renderTargetSerial = GetAttachmentSerial(attachment); if (renderTargetSerial != mAppliedRenderTargetSerial) { // Apply the render target on the device IDirect3DSurface9 *renderTargetSurface = NULL; - RenderTarget *renderTarget = attachment->getRenderTarget(); + RenderTarget9 *renderTarget = d3d9::GetAttachmentRenderTarget(attachment); if (renderTarget) { - renderTargetSurface = RenderTarget9::makeRenderTarget9(renderTarget)->getSurface(); + renderTargetSurface = renderTarget->getSurface(); } if (!renderTargetSurface) { - ERR("render target pointer unexpectedly null."); - return false; // Context must be lost + return gl::Error(GL_OUT_OF_MEMORY, "Internal render target pointer unexpectedly null."); } mDevice->SetRenderTarget(0, renderTargetSurface); @@ -1200,12 +1186,12 @@ bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) unsigned int stencilbufferSerial = 0; if (depthStencil) { - depthbufferSerial = depthStencil->getSerial(); + depthbufferSerial = GetAttachmentSerial(depthStencil); } else if (framebuffer->getStencilbuffer()) { depthStencil = framebuffer->getStencilbuffer(); - stencilbufferSerial = depthStencil->getSerial(); + stencilbufferSerial = GetAttachmentSerial(depthStencil); } if (depthbufferSerial != mAppliedDepthbufferSerial || @@ -1219,17 +1205,16 @@ bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) if (depthStencil) { IDirect3DSurface9 *depthStencilSurface = NULL; - RenderTarget *depthStencilRenderTarget = depthStencil->getDepthStencil(); + rx::RenderTarget9 *depthStencilRenderTarget = d3d9::GetAttachmentRenderTarget(depthStencil); if (depthStencilRenderTarget) { - depthStencilSurface = RenderTarget9::makeRenderTarget9(depthStencilRenderTarget)->getSurface(); + depthStencilSurface = depthStencilRenderTarget->getSurface(); } if (!depthStencilSurface) { - ERR("depth stencil pointer unexpectedly null."); - return false; // Context must be lost + return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil pointer unexpectedly null."); } mDevice->SetDepthStencilSurface(depthStencilSurface); @@ -1272,42 +1257,43 @@ bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) mRenderTargetDescInitialized = true; } - return true; + return gl::Error(GL_NO_ERROR); } -GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], - GLint first, GLsizei count, GLsizei instances) +gl::Error Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], + GLint first, GLsizei count, GLsizei instances) { TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; - GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances); - if (err != GL_NO_ERROR) + gl::Error error = mVertexDataManager->prepareVertexData(vertexAttributes, currentValues, programBinary, first, count, attributes, instances); + if (error.isError()) { - return err; + return error; } return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw); } // Applies the indices and element array bindings to the Direct3D 9 device -GLenum Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) +gl::Error Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) { - GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); - - if (err == GL_NO_ERROR) + gl::Error error = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); + if (error.isError()) { - // Directly binding the storage buffer is not supported for d3d9 - ASSERT(indexInfo->storage == NULL); + return error; + } - if (indexInfo->serial != mAppliedIBSerial) - { - IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer); + // Directly binding the storage buffer is not supported for d3d9 + ASSERT(indexInfo->storage == NULL); - mDevice->SetIndices(indexBuffer->getBuffer()); - mAppliedIBSerial = indexInfo->serial; - } + if (indexInfo->serial != mAppliedIBSerial) + { + IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer); + + mDevice->SetIndices(indexBuffer->getBuffer()); + mAppliedIBSerial = indexInfo->serial; } - return err; + return gl::Error(GL_NO_ERROR); } void Renderer9::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) @@ -1315,7 +1301,7 @@ void Renderer9::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffe UNREACHABLE(); } -void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) +gl::Error Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) { ASSERT(!transformFeedbackActive); @@ -1323,62 +1309,66 @@ void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool t if (mode == GL_LINE_LOOP) { - drawLineLoop(count, GL_NONE, NULL, 0, NULL); + return drawLineLoop(count, GL_NONE, NULL, 0, NULL); } else if (instances > 0) { - StaticIndexBufferInterface *countingIB = mIndexDataManager->getCountingIndices(count); - if (countingIB) + StaticIndexBufferInterface *countingIB = NULL; + gl::Error error = getCountingIB(count, &countingIB); + if (error.isError()) { - if (mAppliedIBSerial != countingIB->getSerial()) - { - IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer()); + return error; + } - mDevice->SetIndices(indexBuffer->getBuffer()); - mAppliedIBSerial = countingIB->getSerial(); - } + if (mAppliedIBSerial != countingIB->getSerial()) + { + IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer()); - for (int i = 0; i < mRepeatDraw; i++) - { - mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount); - } + mDevice->SetIndices(indexBuffer->getBuffer()); + mAppliedIBSerial = countingIB->getSerial(); } - else + + for (int i = 0; i < mRepeatDraw; i++) { - ERR("Could not create a counting index buffer for glDrawArraysInstanced."); - return gl::error(GL_OUT_OF_MEMORY); + 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); } } -void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/) +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) { - drawIndexedPoints(count, type, indices, indexInfo.minIndex, elementArrayBuffer); + return drawIndexedPoints(count, type, indices, minIndex, elementArrayBuffer); } else if (mode == GL_LINE_LOOP) { - drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); + return drawLineLoop(count, type, indices, minIndex, elementArrayBuffer); } else { for (int i = 0; i < mRepeatDraw; i++) { - GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; - mDevice->DrawIndexedPrimitive(mPrimitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount); + GLsizei vertexCount = static_cast(indexInfo.indexRange.length()) + 1; + mDevice->DrawIndexedPrimitive(mPrimitiveType, -minIndex, minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount); } + return gl::Error(GL_NO_ERROR); } } -void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +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) @@ -1396,13 +1386,11 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, if (!mLineLoopIB) { mLineLoopIB = new StreamingIndexBufferInterface(this); - if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) + gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT); + if (error.isError()) { - delete mLineLoopIB; - mLineLoopIB = NULL; - - ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); + SafeDelete(mLineLoopIB); + return error; } } @@ -1411,23 +1399,22 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) { - ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); - return gl::error(GL_OUT_OF_MEMORY); + 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); - if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) + const unsigned int spaceNeeded = (static_cast(count)+1) * sizeof(unsigned int); + gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); + if (error.isError()) { - ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); + return error; } void* mappedMemory = NULL; unsigned int offset = 0; - if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) + error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); + if (error.isError()) { - ERR("Could not map index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); + return error; } startIndex = static_cast(offset) / 4; @@ -1466,10 +1453,10 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, default: UNREACHABLE(); } - if (!mLineLoopIB->unmapBuffer()) + error = mLineLoopIB->unmapBuffer(); + if (error.isError()) { - ERR("Could not unmap index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); + return error; } } else @@ -1477,13 +1464,11 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, if (!mLineLoopIB) { mLineLoopIB = new StreamingIndexBufferInterface(this); - if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT)) + gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT); + if (error.isError()) { - delete mLineLoopIB; - mLineLoopIB = NULL; - - ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); + SafeDelete(mLineLoopIB); + return error; } } @@ -1492,23 +1477,22 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned short))) { - ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required."); - return gl::error(GL_OUT_OF_MEMORY); + 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); - if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT)) + gl::Error error = mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); + if (error.isError()) { - ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); + return error; } void* mappedMemory = NULL; unsigned int offset; - if (mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) + error = mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset); + if (error.isError()) { - ERR("Could not map index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); + return error; } startIndex = static_cast(offset) / 2; @@ -1547,10 +1531,10 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, default: UNREACHABLE(); } - if (!mLineLoopIB->unmapBuffer()) + error = mLineLoopIB->unmapBuffer(); + if (error.isError()) { - ERR("Could not unmap index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); + return error; } } @@ -1563,19 +1547,23 @@ void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, } mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count); + + return gl::Error(GL_NO_ERROR); } template -static void drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices, int minIndex) +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); } -void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +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. @@ -1589,15 +1577,87 @@ void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indi switch (type) { - case GL_UNSIGNED_BYTE: drawPoints(mDevice, count, indices, minIndex); break; - case GL_UNSIGNED_SHORT: drawPoints(mDevice, count, indices, minIndex); break; - case GL_UNSIGNED_INT: drawPoints(mDevice, count, indices, minIndex); break; - default: UNREACHABLE(); + 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); } } -void Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, bool transformFeedbackActive) +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); @@ -1632,9 +1692,11 @@ void Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexF mDxUniformsDirty = true; mAppliedProgramSerial = programSerial; } + + return gl::Error(GL_NO_ERROR); } -void Renderer9::applyUniforms(const gl::ProgramBinary &programBinary) +gl::Error Renderer9::applyUniforms(const gl::ProgramBinary &programBinary) { const std::vector &uniformArray = programBinary.getUniforms(); @@ -1686,6 +1748,8 @@ void Renderer9::applyUniforms(const gl::ProgramBinary &programBinary) 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) @@ -1733,13 +1797,13 @@ void Renderer9::applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v applyUniformnfv(targetUniform, (GLfloat*)vector); } -void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) +gl::Error Renderer9::clear(const gl::ClearParameters &clearParams, 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; + return gl::Error(GL_INVALID_OPERATION); } bool clearColor = clearParams.clearColor[0]; @@ -1749,7 +1813,7 @@ void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *f { // Clearing individual buffers other than buffer zero is not supported by Renderer9 and ES 2.0 UNREACHABLE(); - return; + return gl::Error(GL_INVALID_OPERATION); } } @@ -1759,7 +1823,7 @@ void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *f unsigned int stencilUnmasked = 0x0; if (clearParams.clearStencil && frameBuffer->hasStencil()) { - unsigned int stencilSize = gl::GetStencilBits(frameBuffer->getStencilbuffer()->getActualFormat()); + unsigned int stencilSize = gl::GetInternalFormatInfo((frameBuffer->getStencilbuffer()->getActualFormat())).stencilBits; stencilUnmasked = (0x1 << stencilSize) - 1; } @@ -1770,29 +1834,19 @@ void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *f D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0); if (clearColor) { - gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer(); - GLenum internalFormat = attachment->getInternalFormat(); - GLenum actualFormat = attachment->getActualFormat(); - - GLuint internalRedBits = gl::GetRedBits(internalFormat); - GLuint internalGreenBits = gl::GetGreenBits(internalFormat); - GLuint internalBlueBits = gl::GetBlueBits(internalFormat); - GLuint internalAlphaBits = gl::GetAlphaBits(internalFormat); + const gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer(); + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat()); + const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat()); - GLuint actualRedBits = gl::GetRedBits(actualFormat); - GLuint actualGreenBits = gl::GetGreenBits(actualFormat); - GLuint actualBlueBits = gl::GetBlueBits(actualFormat); - GLuint actualAlphaBits = gl::GetAlphaBits(actualFormat); + 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)); - color = D3DCOLOR_ARGB(gl::unorm<8>((internalAlphaBits == 0 && actualAlphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha), - gl::unorm<8>((internalRedBits == 0 && actualRedBits > 0) ? 0.0f : clearParams.colorFClearValue.red), - gl::unorm<8>((internalGreenBits == 0 && actualGreenBits > 0) ? 0.0f : clearParams.colorFClearValue.green), - gl::unorm<8>((internalBlueBits == 0 && actualBlueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue)); - - if ((internalRedBits > 0 && !clearParams.colorMaskRed) || - (internalGreenBits > 0 && !clearParams.colorMaskGreen) || - (internalBlueBits > 0 && !clearParams.colorMaskBlue) || - (internalAlphaBits > 0 && !clearParams.colorMaskAlpha)) + if ((formatInfo.redBits > 0 && !clearParams.colorMaskRed) || + (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) || + (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) || + (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha)) { needMaskedColorClear = true; } @@ -1956,6 +2010,8 @@ void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *f mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil); } + + return gl::Error(GL_NO_ERROR); } void Renderer9::markAllStateDirty() @@ -1972,12 +2028,15 @@ void Renderer9::markAllStateDirty() mForceSetViewport = true; mForceSetBlendState = true; - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) + ASSERT(mForceSetVertexSamplerStates.size() == mCurVertexTextureSerials.size()); + for (unsigned int i = 0; i < mForceSetVertexSamplerStates.size(); i++) { mForceSetVertexSamplerStates[i] = true; mCurVertexTextureSerials[i] = 0; } - for (unsigned int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++) + + ASSERT(mForceSetPixelSamplerStates.size() == mCurPixelTextureSerials.size()); + for (unsigned int i = 0; i < mForceSetPixelSamplerStates.size(); i++) { mForceSetPixelSamplerStates[i] = true; mCurPixelTextureSerials[i] = 0; @@ -2009,6 +2068,7 @@ void Renderer9::releaseDeviceResources() SafeDelete(mVertexDataManager); SafeDelete(mIndexDataManager); SafeDelete(mLineLoopIB); + SafeDelete(mCountingIB); for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) { @@ -2219,43 +2279,6 @@ GUID Renderer9::getAdapterIdentifier() const return mAdapterIdentifier.DeviceIdentifier; } -Renderer9::MultisampleSupportInfo Renderer9::getMultiSampleSupport(D3DFORMAT format) -{ - MultisampleSupportInfo support = { 0 }; - - for (unsigned int multiSampleIndex = 0; multiSampleIndex < ArraySize(support.supportedSamples); multiSampleIndex++) - { - HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format, TRUE, - (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL); - - if (SUCCEEDED(result)) - { - support.supportedSamples[multiSampleIndex] = true; - if (multiSampleIndex != D3DMULTISAMPLE_NONMASKABLE) - { - support.maxSupportedSamples = std::max(support.maxSupportedSamples, multiSampleIndex); - } - } - else - { - support.supportedSamples[multiSampleIndex] = false; - } - } - - return support; -} - -unsigned int Renderer9::getMaxVertexTextureImageUnits() const -{ - META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); - return mVertexTextureSupport ? MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 : 0; -} - -unsigned int Renderer9::getMaxCombinedTextureImageUnits() const -{ - return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits(); -} - unsigned int Renderer9::getReservedVertexUniformVectors() const { return 2; // dx_ViewAdjust and dx_DepthRange. @@ -2266,33 +2289,6 @@ unsigned int Renderer9::getReservedFragmentUniformVectors() const return 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange. } -unsigned int Renderer9::getMaxVertexUniformVectors() const -{ - return MAX_VERTEX_CONSTANT_VECTORS_D3D9 - getReservedVertexUniformVectors(); -} - -unsigned int Renderer9::getMaxFragmentUniformVectors() const -{ - const int maxPixelConstantVectors = (getMajorShaderModel() >= 3) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 : MAX_PIXEL_CONSTANT_VECTORS_SM2; - - return maxPixelConstantVectors - getReservedFragmentUniformVectors(); -} - -unsigned int Renderer9::getMaxVaryingVectors() const -{ - return (getMajorShaderModel() >= 3) ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2; -} - -unsigned int Renderer9::getMaxVertexShaderUniformBuffers() const -{ - return 0; -} - -unsigned int Renderer9::getMaxFragmentShaderUniformBuffers() const -{ - return 0; -} - unsigned int Renderer9::getReservedVertexUniformBuffers() const { return 0; @@ -2303,26 +2299,6 @@ unsigned int Renderer9::getReservedFragmentUniformBuffers() const return 0; } -unsigned int Renderer9::getMaxTransformFeedbackBuffers() const -{ - return 0; -} - -unsigned int Renderer9::getMaxTransformFeedbackSeparateComponents() const -{ - return 0; -} - -unsigned int Renderer9::getMaxTransformFeedbackInterleavedComponents() const -{ - return 0; -} - -unsigned int Renderer9::getMaxUniformBufferSize() const -{ - return 0; -} - bool Renderer9::getShareHandleSupport() const { // PIX doesn't seem to support using share handles, so disable them. @@ -2334,25 +2310,6 @@ bool Renderer9::getPostSubBufferSupport() const return true; } -int Renderer9::getMaxRecommendedElementsIndices() const -{ - // ES3 only - UNREACHABLE(); - return 0; -} - -int Renderer9::getMaxRecommendedElementsVertices() const -{ - // ES3 only - UNREACHABLE(); - return 0; -} - -bool Renderer9::getSRGBTextureSupport() const -{ - return false; -} - int Renderer9::getMajorShaderModel() const { return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion); @@ -2373,92 +2330,14 @@ int Renderer9::getMaxSwapInterval() const return mMaxSwapInterval; } -int Renderer9::getMaxSupportedSamples() const -{ - return mMaxSupportedSamples; -} - -GLsizei Renderer9::getMaxSupportedFormatSamples(GLenum internalFormat) const -{ - D3DFORMAT format = gl_d3d9::GetTextureFormat(internalFormat); - MultisampleSupportMap::const_iterator itr = mMultiSampleSupport.find(format); - return (itr != mMultiSampleSupport.end()) ? mMaxSupportedSamples : 0; -} - -GLsizei Renderer9::getNumSampleCounts(GLenum internalFormat) const -{ - D3DFORMAT format = gl_d3d9::GetTextureFormat(internalFormat); - MultisampleSupportMap::const_iterator iter = mMultiSampleSupport.find(format); - - unsigned int numCounts = 0; - if (iter != mMultiSampleSupport.end()) - { - const MultisampleSupportInfo& info = iter->second; - for (int i = 0; i < D3DMULTISAMPLE_16_SAMPLES; i++) - { - if (i != D3DMULTISAMPLE_NONMASKABLE && info.supportedSamples[i]) - { - numCounts++; - } - } - } - - return numCounts; -} - -void Renderer9::getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const -{ - D3DFORMAT format = gl_d3d9::GetTextureFormat(internalFormat); - MultisampleSupportMap::const_iterator iter = mMultiSampleSupport.find(format); - - if (iter != mMultiSampleSupport.end()) - { - const MultisampleSupportInfo& info = iter->second; - int bufPos = 0; - for (int i = D3DMULTISAMPLE_16_SAMPLES; i >= 0 && bufPos < bufSize; i--) - { - if (i != D3DMULTISAMPLE_NONMASKABLE && info.supportedSamples[i]) - { - params[bufPos++] = i; - } - } - } -} - -int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const -{ - if (requested == 0) - { - return requested; - } - - MultisampleSupportMap::const_iterator itr = mMultiSampleSupport.find(format); - if (itr == mMultiSampleSupport.end()) - { - if (format == D3DFMT_UNKNOWN) - return 0; - return -1; - } - - for (unsigned int i = requested; i < ArraySize(itr->second.supportedSamples); ++i) - { - if (itr->second.supportedSamples[i] && i != D3DMULTISAMPLE_NONMASKABLE) - { - return i; - } - } - - return -1; -} - -bool Renderer9::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) +bool Renderer9::copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source) { bool result = false; if (source && dest) { - TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source->getStorageInstance()); - TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest->getStorageInstance()); + TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source); + TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest); int levels = source9->getLevelCount(); for (int i = 0; i < levels; ++i) @@ -2481,14 +2360,14 @@ bool Renderer9::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStora return result; } -bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) +bool Renderer9::copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source) { bool result = false; if (source && dest) { - TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source->getStorageInstance()); - TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest->getStorageInstance()); + TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source); + TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest); int levels = source9->getLevelCount(); for (int f = 0; f < 6; f++) { @@ -2513,14 +2392,14 @@ bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureSto return result; } -bool Renderer9::copyToRenderTarget(TextureStorageInterface3D *dest, TextureStorageInterface3D *source) +bool Renderer9::copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source) { // 3D textures are not available in the D3D9 backend. UNREACHABLE(); return false; } -bool Renderer9::copyToRenderTarget(TextureStorageInterface2DArray *dest, TextureStorageInterface2DArray *source) +bool Renderer9::copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source) { // 2D array textures are not supported by the D3D9 backend. UNREACHABLE(); @@ -2544,8 +2423,8 @@ D3DPOOL Renderer9::getBufferPool(DWORD usage) const return D3DPOOL_DEFAULT; } -bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) +bool 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; @@ -2553,11 +2432,11 @@ bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sou rect.right = sourceRect.x + sourceRect.width; rect.bottom = sourceRect.y + sourceRect.height; - return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, level); + return mBlit->copy2D(framebuffer, rect, destFormat, xoffset, yoffset, storage, level); } -bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) +bool 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; @@ -2565,19 +2444,19 @@ bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sou rect.right = sourceRect.x + sourceRect.width; rect.bottom = sourceRect.y + sourceRect.height; - return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level); + return mBlit->copyCube(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level); } -bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface3D *storage, GLint level) +bool 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 false; } -bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level) +bool 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(); @@ -2602,11 +2481,11 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & if (readBuffer) { - readRenderTarget = RenderTarget9::makeRenderTarget9(readBuffer->getRenderTarget()); + readRenderTarget = d3d9::GetAttachmentRenderTarget(readBuffer); } if (drawBuffer) { - drawRenderTarget = RenderTarget9::makeRenderTarget9(drawBuffer->getRenderTarget()); + drawRenderTarget = d3d9::GetAttachmentRenderTarget(drawBuffer); } if (readRenderTarget) @@ -2731,11 +2610,11 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & if (readBuffer) { - readDepthStencil = RenderTarget9::makeRenderTarget9(readBuffer->getDepthStencil()); + readDepthStencil = d3d9::GetAttachmentRenderTarget(readBuffer); } if (drawBuffer) { - drawDepthStencil = RenderTarget9::makeRenderTarget9(drawBuffer->getDepthStencil()); + drawDepthStencil = d3d9::GetAttachmentRenderTarget(drawBuffer); } if (readDepthStencil) @@ -2768,8 +2647,8 @@ bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle & return true; } -void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels) +gl::Error Renderer9::readPixels(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); @@ -2779,7 +2658,7 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz if (colorbuffer) { - renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); + renderTarget = d3d9::GetAttachmentRenderTarget(colorbuffer); } if (renderTarget) @@ -2790,7 +2669,7 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz if (!surface) { // context must be lost - return; + return gl::Error(GL_NO_ERROR); } D3DSURFACE_DESC desc; @@ -2800,7 +2679,7 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz { UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target SafeRelease(surface); - return gl::error(GL_OUT_OF_MEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "ReadPixels is unimplemented for multisampled framebuffer attachments."); } HRESULT result; @@ -2812,7 +2691,7 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz { // Use the pixels ptr as a shared handle to write directly into client's memory result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, - D3DPOOL_SYSTEMMEM, &systemSurface, &pixels); + D3DPOOL_SYSTEMMEM, &systemSurface, reinterpret_cast(&pixels)); if (FAILED(result)) { // Try again without the shared handle @@ -2828,7 +2707,7 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz { ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); SafeRelease(surface); - return gl::error(GL_OUT_OF_MEMORY); + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for ReadPixels."); } } @@ -2844,20 +2723,19 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz if (d3d9::isDeviceLostError(result)) { notifyDeviceLost(); - return gl::error(GL_OUT_OF_MEMORY); } else { UNREACHABLE(); - return; } + return gl::Error(GL_OUT_OF_MEMORY, "Failed to read internal render target data."); } if (directToPixels) { SafeRelease(systemSurface); - return; + return gl::Error(GL_NO_ERROR); } RECT rect; @@ -2874,44 +2752,40 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz UNREACHABLE(); SafeRelease(systemSurface); - return; // No sensible error to generate + return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal render target."); } - unsigned char *source; + uint8_t *source; int inputPitch; if (pack.reverseRowOrder) { - source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); + source = reinterpret_cast(lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); inputPitch = -lock.Pitch; } else { - source = (unsigned char*)lock.pBits; + source = reinterpret_cast(lock.pBits); inputPitch = lock.Pitch; } - GLenum sourceInternalFormat = d3d9_gl::GetInternalFormat(desc.Format); - GLenum sourceFormat = gl::GetFormat(sourceInternalFormat); - GLenum sourceType = gl::GetType(sourceInternalFormat); - - GLuint sourcePixelSize = gl::GetPixelBytes(sourceInternalFormat); - - if (sourceFormat == format && sourceType == type) + 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 - unsigned char *dest = static_cast(pixels); for (int y = 0; y < rect.bottom - rect.top; y++) { - memcpy(dest + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourcePixelSize); + memcpy(pixels + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourceFormatInfo.pixelBytes); } } else { - GLenum destInternalFormat = gl::GetSizedInternalFormat(format, type); - GLuint destPixelSize = gl::GetPixelBytes(destInternalFormat); - GLuint sourcePixelSize = gl::GetPixelBytes(sourceInternalFormat); + 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); - ColorCopyFunction fastCopyFunc = d3d9::GetFastCopyFunction(desc.Format, format, type); if (fastCopyFunc) { // Fast copy is possible through some special function @@ -2919,8 +2793,8 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz { for (int x = 0; x < rect.right - rect.left; x++) { - void *dest = static_cast(pixels) + y * outputPitch + x * destPixelSize; - void *src = static_cast(source) + y * inputPitch + x * sourcePixelSize; + uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes; + const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes; fastCopyFunc(src, dest); } @@ -2928,22 +2802,18 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz } else { - ColorReadFunction readFunc = d3d9::GetColorReadFunction(desc.Format); - ColorWriteFunction writeFunc = gl::GetColorWriteFunction(format, type); - - gl::ColorF temp; - + 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++) { - void *dest = reinterpret_cast(pixels) + y * outputPitch + x * destPixelSize; - void *src = source + y * inputPitch + x * sourcePixelSize; + 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. - readFunc(src, &temp); - writeFunc(&temp, dest); + sourceD3DFormatInfo.colorReadFunction(src, temp); + destFormatTypeInfo.colorWriteFunction(temp, dest); } } } @@ -2951,6 +2821,8 @@ void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsiz systemSurface->UnlockRect(); SafeRelease(systemSurface); + + return gl::Error(GL_NO_ERROR); } RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth) @@ -2977,6 +2849,21 @@ RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format return renderTarget; } +ShaderImpl *Renderer9::createShader(GLenum type) +{ + return new ShaderD3D(type, this); +} + +ProgramImpl *Renderer9::createProgram() +{ + return new ProgramD3D(this); +} + +void Renderer9::releaseShaderCompiler() +{ + ShaderD3D::releaseCompiler(); +} + ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type, const std::vector &transformFeedbackVaryings, bool separatedOutputBuffers) @@ -3200,24 +3087,16 @@ TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat, bo return NULL; } -Texture2DImpl *Renderer9::createTexture2D() -{ - return new TextureD3D_2D(this); -} - -TextureCubeImpl *Renderer9::createTextureCube() -{ - return new TextureD3D_Cube(this); -} - -Texture3DImpl *Renderer9::createTexture3D() +TextureImpl *Renderer9::createTexture(GLenum target) { - return new TextureD3D_3D(this); -} + switch(target) + { + case GL_TEXTURE_2D: return new TextureD3D_2D(this); + case GL_TEXTURE_CUBE_MAP: return new TextureD3D_Cube(this); + default: UNREACHABLE(); + } -Texture2DArrayImpl *Renderer9::createTexture2DArray() -{ - return new TextureD3D_2DArray(this); + return NULL; } bool Renderer9::getLUID(LUID *adapterLuid) const @@ -3234,20 +3113,14 @@ bool Renderer9::getLUID(LUID *adapterLuid) const return false; } -GLenum Renderer9::getNativeTextureFormat(GLenum internalFormat) const -{ - return d3d9_gl::GetInternalFormat(gl_d3d9::GetTextureFormat(internalFormat)); -} - rx::VertexConversionType Renderer9::getVertexConversionType(const gl::VertexFormat &vertexFormat) const { - return d3d9::GetVertexConversionType(vertexFormat); + return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormat).conversionType; } GLenum Renderer9::getVertexComponentType(const gl::VertexFormat &vertexFormat) const { - D3DDECLTYPE declType = d3d9::GetNativeVertexFormat(vertexFormat); - return d3d9::GetDeclTypeComponentType(declType); + return d3d9::GetVertexFormatInfo(getCapsDeclTypes(), vertexFormat).componentType; } void Renderer9::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h index 070623c9db..dd5f30268a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h @@ -27,6 +27,7 @@ namespace rx class VertexDataManager; class IndexDataManager; class StreamingIndexBufferInterface; +class StaticIndexBufferInterface; struct TranslatedAttribute; class Blit9; @@ -59,38 +60,38 @@ class Renderer9 : public Renderer IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length); HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer); HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer); - virtual void generateSwizzle(gl::Texture *texture); - virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); - virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); + virtual gl::Error generateSwizzle(gl::Texture *texture); + virtual gl::Error setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); + virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture); - virtual bool setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]); + virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]); - virtual void setRasterizerState(const gl::RasterizerState &rasterState); - virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, - unsigned int sampleMask); - virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW); + virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState); + virtual gl::Error setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, + unsigned int sampleMask); + virtual gl::Error setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW); virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); - virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, bool ignoreViewport); - virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); - virtual void applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, - bool rasterizerDiscard, bool transformFeedbackActive); - virtual void applyUniforms(const gl::ProgramBinary &programBinary); + virtual gl::Error applyRenderTarget(gl::Framebuffer *frameBuffer); + virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive); + virtual gl::Error applyUniforms(const gl::ProgramBinary &programBinary); virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount); - virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], - GLint first, GLsizei count, GLsizei instances); - virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); + virtual gl::Error applyVertexBuffer(gl::ProgramBinary *programBinary, const gl::VertexAttribute vertexAttributes[], const gl::VertexAttribCurrentValueData currentValues[], + 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(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]); - virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive); - virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, - gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); + 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); - virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); + virtual gl::Error clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); virtual void markAllStateDirty(); @@ -105,63 +106,49 @@ class Renderer9 : public Renderer virtual std::string getRendererDescription() const; virtual GUID getAdapterIdentifier() const; - virtual unsigned int getMaxVertexTextureImageUnits() const; - virtual unsigned int getMaxCombinedTextureImageUnits() const; virtual unsigned int getReservedVertexUniformVectors() const; virtual unsigned int getReservedFragmentUniformVectors() const; - virtual unsigned int getMaxVertexUniformVectors() const; - virtual unsigned int getMaxFragmentUniformVectors() const; - virtual unsigned int getMaxVaryingVectors() const; - virtual unsigned int getMaxVertexShaderUniformBuffers() const; - virtual unsigned int getMaxFragmentShaderUniformBuffers() const; virtual unsigned int getReservedVertexUniformBuffers() const; virtual unsigned int getReservedFragmentUniformBuffers() const; - virtual unsigned int getMaxTransformFeedbackBuffers() const; - virtual unsigned int getMaxTransformFeedbackSeparateComponents() const; - virtual unsigned int getMaxTransformFeedbackInterleavedComponents() const; - virtual unsigned int getMaxUniformBufferSize() const; virtual bool getShareHandleSupport() const; virtual bool getPostSubBufferSupport() const; - virtual int getMaxRecommendedElementsIndices() const; - virtual int getMaxRecommendedElementsVertices() const; - virtual bool getSRGBTextureSupport() const; virtual int getMajorShaderModel() const; DWORD getCapsDeclTypes() const; virtual int getMinSwapInterval() const; virtual int getMaxSwapInterval() const; - virtual GLsizei getMaxSupportedSamples() const; - virtual GLsizei getMaxSupportedFormatSamples(GLenum internalFormat) const; - virtual GLsizei getNumSampleCounts(GLenum internalFormat) const; - virtual void getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const; - int getNearestSupportedSamples(D3DFORMAT format, int requested) const; - // Pixel operations - virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source); - virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source); - virtual bool copyToRenderTarget(TextureStorageInterface3D *dest, TextureStorageInterface3D *source); - virtual bool copyToRenderTarget(TextureStorageInterface2DArray *dest, TextureStorageInterface2DArray *source); - - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface3D *storage, GLint level); - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level); + virtual bool copyToRenderTarget2D(TextureStorage *dest, TextureStorage *source); + virtual bool copyToRenderTargetCube(TextureStorage *dest, TextureStorage *source); + virtual bool copyToRenderTarget3D(TextureStorage *dest, TextureStorage *source); + virtual bool copyToRenderTarget2DArray(TextureStorage *dest, TextureStorage *source); + + virtual bool copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level); + virtual bool copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level); + virtual bool copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); + virtual bool copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level); virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter); - virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, - GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels); + + virtual gl::Error readPixels(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 RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples); + // Shader creation + virtual ShaderImpl *createShader(GLenum type); + virtual ProgramImpl *createProgram(); + // Shader operations + virtual void releaseShaderCompiler(); virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, const std::vector &transformFeedbackVaryings, bool separatedOutputBuffers); @@ -180,10 +167,7 @@ class Renderer9 : public Renderer virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); // Texture creation - virtual Texture2DImpl *createTexture2D(); - virtual TextureCubeImpl *createTextureCube(); - virtual Texture3DImpl *createTexture3D(); - virtual Texture2DArrayImpl *createTexture2DArray(); + virtual TextureImpl *createTexture(GLenum target); // Buffer creation virtual BufferImpl *createBuffer(); @@ -197,6 +181,9 @@ class Renderer9 : public Renderer virtual QueryImpl *createQuery(GLenum type); virtual FenceImpl *createFence(); + // Transform Feedback creation + virtual TransformFeedbackImpl* createTransformFeedback(); + // Buffer-to-texture and Texture-to-buffer copies virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const; virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, @@ -208,7 +195,6 @@ class Renderer9 : public Renderer D3DPOOL getTexturePool(DWORD usage) const; virtual bool getLUID(LUID *adapterLuid) const; - virtual GLenum getNativeTextureFormat(GLenum internalFormat) const; virtual rx::VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const; virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const; @@ -223,8 +209,10 @@ class Renderer9 : public Renderer void applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v); void applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v); - void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); - void drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); + 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); bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); gl::FramebufferAttachment *getNullColorbuffer(gl::FramebufferAttachment *depthbuffer); @@ -269,17 +257,6 @@ class Renderer9 : public Renderer bool mVertexTextureSupport; - struct MultisampleSupportInfo - { - bool supportedSamples[D3DMULTISAMPLE_16_SAMPLES + 1]; - unsigned int maxSupportedSamples; - }; - typedef std::map MultisampleSupportMap; - MultisampleSupportMap mMultiSampleSupport; - unsigned int mMaxSupportedSamples; - - MultisampleSupportInfo getMultiSampleSupport(D3DFORMAT format); - // current render target states unsigned int mAppliedRenderTargetSerial; unsigned int mAppliedDepthbufferSerial; @@ -318,15 +295,15 @@ class Renderer9 : public Renderer GLuint mCurSampleMask; // Currently applied sampler states - bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + std::vector mForceSetVertexSamplerStates; + std::vector mCurVertexSamplerStates; - bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; - gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; + std::vector mForceSetPixelSamplerStates; + std::vector mCurPixelSamplerStates; // Currently applied textures - unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS]; + std::vector mCurVertexTextureSerials; + std::vector mCurPixelTextureSerials; unsigned int mAppliedIBSerial; IDirect3DVertexShader9 *mAppliedVertexShader; @@ -347,6 +324,7 @@ class Renderer9 : public Renderer IndexDataManager *mIndexDataManager; StreamingIndexBufferInterface *mLineLoopIB; + StaticIndexBufferInterface *mCountingIB; enum { NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12 }; struct NullColorbufferCacheEntry diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h index a03528c9b5..2ad3022839 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h @@ -12,6 +12,10 @@ #include "common/debug.h" +#include +#include +#include + namespace rx { template diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp index c10ddbf6ce..bc7120461b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp index c6567b635f..0aeaabb1ca 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -50,7 +49,7 @@ void SwapChain9::release() static DWORD convertInterval(EGLint interval) { -#if ANGLE_FORCE_VSYNC_OFF +#ifdef ANGLE_FORCE_VSYNC_OFF return D3DPRESENT_INTERVAL_IMMEDIATE; #else switch(interval) @@ -101,9 +100,10 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI pShareHandle = &mShareHandle; } + const d3d9::TextureFormat &backBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mBackBufferFormat); result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, - gl_d3d9::GetTextureFormat(mBackBufferFormat), - D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle); + backBufferd3dFormatInfo.texFormat, D3DPOOL_DEFAULT, &mOffscreenTexture, + pShareHandle); if (FAILED(result)) { ERR("Could not create offscreen texture: %08lX", result); @@ -150,12 +150,14 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI SafeRelease(oldRenderTarget); } + const d3d9::TextureFormat &depthBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mDepthBufferFormat); + if (mWindow) { D3DPRESENT_PARAMETERS presentParameters = {0}; - presentParameters.AutoDepthStencilFormat = gl_d3d9::GetRenderFormat(mDepthBufferFormat); + presentParameters.AutoDepthStencilFormat = depthBufferd3dFormatInfo.renderFormat; presentParameters.BackBufferCount = 1; - presentParameters.BackBufferFormat = gl_d3d9::GetRenderFormat(mBackBufferFormat); + presentParameters.BackBufferFormat = backBufferd3dFormatInfo.renderFormat; presentParameters.EnableAutoDepthStencil = FALSE; presentParameters.Flags = 0; presentParameters.hDeviceWindow = mWindow; @@ -207,7 +209,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI if (mDepthBufferFormat != GL_NONE) { result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, - gl_d3d9::GetRenderFormat(mDepthBufferFormat), + depthBufferd3dFormatInfo.renderFormat, D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL); if (FAILED(result)) diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp index b065ee80fe..f44e33db18 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -9,15 +8,15 @@ // classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the // D3D9 texture. -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d/TextureD3D.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" #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 { @@ -43,12 +42,13 @@ DWORD TextureStorage9::GetTextureUsage(GLenum internalformat, bool renderTarget) { DWORD d3dusage = 0; - if (gl::GetDepthBits(internalformat) > 0 || - gl::GetStencilBits(internalformat) > 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 && (gl_d3d9::GetRenderFormat(internalformat) != D3DFMT_UNKNOWN)) + else if (renderTarget && (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN)) { d3dusage |= D3DUSAGE_RENDERTARGET; } @@ -95,6 +95,7 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain mRenderTarget = NULL; initializeRenderTarget(); + initializeSerials(1, 1); } TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) @@ -107,11 +108,11 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, GLenum internalformat if (width > 0 && height > 0) { IDirect3DDevice9 *device = mRenderer->getDevice(); - D3DFORMAT format = gl_d3d9::GetTextureFormat(internalformat); - d3d9::MakeValidSize(false, format, &width, &height, &mTopLevel); + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); + d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &width, &height, &mTopLevel); UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels; - HRESULT result = device->CreateTexture(width, height, creationLevels, getUsage(), format, getPool(), &mTexture, NULL); + HRESULT result = device->CreateTexture(width, height, creationLevels, getUsage(), d3dFormatInfo.texFormat, getPool(), &mTexture, NULL); if (FAILED(result)) { @@ -121,6 +122,7 @@ TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, GLenum internalformat } initializeRenderTarget(); + initializeSerials(getLevelCount(), 1); } TextureStorage9_2D::~TextureStorage9_2D() @@ -157,23 +159,28 @@ IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty) return surface; } -RenderTarget *TextureStorage9_2D::getRenderTarget(int level) +RenderTarget *TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/) { return mRenderTarget; } -void TextureStorage9_2D::generateMipmap(int level) +void TextureStorage9_2D::generateMipmaps() { - IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false); - IDirect3DSurface9 *lower = getSurfaceLevel(level, true); + // Base level must already be defined - if (upper != NULL && lower != NULL) + for (int level = 1; level < getLevelCount(); level++) { - mRenderer->boxFilter(upper, lower); - } + IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false); + IDirect3DSurface9 *lower = getSurfaceLevel(level, true); + + if (upper != NULL && lower != NULL) + { + mRenderer->boxFilter(upper, lower); + } - SafeRelease(upper); - SafeRelease(lower); + SafeRelease(upper); + SafeRelease(lower); + } } IDirect3DBaseTexture9 *TextureStorage9_2D::getBaseTexture() const @@ -208,11 +215,11 @@ TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, GLenum internalfo { IDirect3DDevice9 *device = mRenderer->getDevice(); int height = size; - D3DFORMAT format = gl_d3d9::GetTextureFormat(internalformat); - d3d9::MakeValidSize(false, format, &size, &height, &mTopLevel); + const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalformat); + d3d9::MakeValidSize(false, d3dFormatInfo.texFormat, &size, &height, &mTopLevel); UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels; - HRESULT result = device->CreateCubeTexture(size, creationLevels, getUsage(), format, getPool(), &mTexture, NULL); + HRESULT result = device->CreateCubeTexture(size, creationLevels, getUsage(), d3dFormatInfo.texFormat, getPool(), &mTexture, NULL); if (FAILED(result)) { @@ -222,6 +229,7 @@ TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, GLenum internalfo } initializeRenderTarget(); + initializeSerials(getLevelCount() * 6, 6); } TextureStorage9_Cube::~TextureStorage9_Cube() @@ -263,23 +271,31 @@ IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, in return surface; } -RenderTarget *TextureStorage9_Cube::getRenderTargetFace(GLenum faceTarget, int level) +RenderTarget *TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index) { - return mRenderTarget[TextureD3D_Cube::targetToIndex(faceTarget)]; + return mRenderTarget[index.layerIndex]; } -void TextureStorage9_Cube::generateMipmap(int faceIndex, int level) +void TextureStorage9_Cube::generateMipmaps() { - IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1, false); - IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, true); + // Base level must already be defined - if (upper != NULL && lower != NULL) + for (int faceIndex = 0; faceIndex < 6; faceIndex++) { - mRenderer->boxFilter(upper, lower); - } + for (int level = 1; level < getLevelCount(); level++) + { + IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level - 1, false); + IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex, level, true); + + if (upper != NULL && lower != NULL) + { + mRenderer->boxFilter(upper, lower); + } - SafeRelease(upper); - SafeRelease(lower); + SafeRelease(upper); + SafeRelease(lower); + } + } } IDirect3DBaseTexture9 *TextureStorage9_Cube::getBaseTexture() const diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h index cc7c155d34..e698c7dd56 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h @@ -34,11 +34,8 @@ class TextureStorage9 : public TextureStorage DWORD getUsage() const; virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0; - virtual RenderTarget *getRenderTarget(int level) { return NULL; } - virtual RenderTarget *getRenderTargetFace(GLenum faceTarget, int level) { return NULL; } - virtual RenderTarget *getRenderTargetLayer(int mipLevel, int layer) { return NULL; } - virtual void generateMipmap(int level) {}; - virtual void generateMipmap(int face, int level) {}; + virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index) = 0; + virtual void generateMipmaps() = 0; virtual int getTopLevel() const; virtual bool isRenderTarget() const; @@ -68,9 +65,9 @@ class TextureStorage9_2D : public TextureStorage9 static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage); IDirect3DSurface9 *getSurfaceLevel(int level, bool dirty); - virtual RenderTarget *getRenderTarget(int level); + virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); virtual IDirect3DBaseTexture9 *getBaseTexture() const; - virtual void generateMipmap(int level); + virtual void generateMipmaps(); private: DISALLOW_COPY_AND_ASSIGN(TextureStorage9_2D); @@ -90,9 +87,9 @@ class TextureStorage9_Cube : public TextureStorage9 static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage); IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level, bool dirty); - virtual RenderTarget *getRenderTargetFace(GLenum faceTarget, int level); + virtual RenderTarget *getRenderTarget(const gl::ImageIndex &index); virtual IDirect3DBaseTexture9 *getBaseTexture() const; - virtual void generateMipmap(int faceIndex, int level); + virtual void generateMipmaps(); private: DISALLOW_COPY_AND_ASSIGN(TextureStorage9_Cube); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp index d260640dbe..4cf7779118 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -8,18 +7,17 @@ // 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/BufferImpl.h" #include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" - #include "libGLESv2/Buffer.h" namespace rx { -VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer) +VertexBuffer9::VertexBuffer9(rx::Renderer9 *renderer) : mRenderer(renderer) { mVertexBuffer = NULL; mBufferSize = 0; @@ -31,7 +29,7 @@ VertexBuffer9::~VertexBuffer9() SafeRelease(mVertexBuffer); } -bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) +gl::Error VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) { SafeRelease(mVertexBuffer); @@ -49,14 +47,13 @@ bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) if (FAILED(result)) { - ERR("Out of memory allocating a vertex buffer of size %lu.", size); - return false; + return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal vertex buffer of size, %lu.", size); } } mBufferSize = size; mDynamicUsage = dynamicUsage; - return true; + return gl::Error(GL_NO_ERROR); } VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer) @@ -65,84 +62,80 @@ VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer) return static_cast(vertexBuffer); } -bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int offset) +gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int offset) { - if (mVertexBuffer) + if (!mVertexBuffer) { - gl::Buffer *buffer = attrib.buffer.get(); + return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + } - int inputStride = gl::ComputeVertexAttributeStride(attrib); - int elementSize = gl::ComputeVertexAttributeTypeSize(attrib); + gl::Buffer *buffer = attrib.buffer.get(); - DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; + int inputStride = gl::ComputeVertexAttributeStride(attrib); + int elementSize = gl::ComputeVertexAttributeTypeSize(attrib); - void *mapPtr = NULL; + DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; - unsigned int mapSize; - if (!spaceRequired(attrib, count, instances, &mapSize)) - { - return false; - } + uint8_t *mapPtr = NULL; - HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags); + unsigned int mapSize; + gl::Error error = spaceRequired(attrib, count, instances, &mapSize); + if (error.isError()) + { + return error; + } - if (FAILED(result)) - { - ERR("Lock failed with error 0x%08x", result); - return false; - } + 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 char *input = NULL; - if (attrib.enabled) + const uint8_t *input = NULL; + if (attrib.enabled) + { + if (buffer) { - if (buffer) - { - BufferImpl *storage = buffer->getImplementation(); - input = static_cast(storage->getData()) + static_cast(attrib.offset); - } - else - { - input = static_cast(attrib.pointer); - } + BufferImpl *storage = buffer->getImplementation(); + input = static_cast(storage->getData()) + static_cast(attrib.offset); } else { - input = reinterpret_cast(currentValue.FloatValues); + 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); - bool needsConversion = (d3d9::GetVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) > 0; - - if (!needsConversion && inputStride == elementSize) - { - size_t copySize = static_cast(count) * static_cast(inputStride); - memcpy(mapPtr, input, copySize); - } - else - { - VertexCopyFunction copyFunction = d3d9::GetVertexCopyFunction(vertexFormat); - copyFunction(input, inputStride, count, mapPtr); - } + if (instances == 0 || attrib.divisor == 0) + { + input += inputStride * start; + } - mVertexBuffer->Unlock(); + gl::VertexFormat vertexFormat(attrib, currentValue.Type); + const d3d9::VertexFormat &d3dVertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat); + bool needsConversion = (d3dVertexInfo.conversionType & VERTEX_CONVERT_CPU) > 0; - return true; + if (!needsConversion && inputStride == elementSize) + { + size_t copySize = static_cast(count) * static_cast(inputStride); + memcpy(mapPtr, input, copySize); } else { - ERR("Vertex buffer not initialized."); - return false; + d3dVertexInfo.copyFunction(input, inputStride, count, mapPtr); } + + mVertexBuffer->Unlock(); + + return gl::Error(GL_NO_ERROR); } -bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, - unsigned int *outSpaceRequired) const +gl::Error VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, + unsigned int *outSpaceRequired) const { return spaceRequired(attrib, count, instances, outSpaceRequired); } @@ -152,7 +145,7 @@ unsigned int VertexBuffer9::getBufferSize() const return mBufferSize; } -bool VertexBuffer9::setBufferSize(unsigned int size) +gl::Error VertexBuffer9::setBufferSize(unsigned int size) { if (size > mBufferSize) { @@ -160,38 +153,33 @@ bool VertexBuffer9::setBufferSize(unsigned int size) } else { - return true; + return gl::Error(GL_NO_ERROR); } } -bool VertexBuffer9::discard() +gl::Error VertexBuffer9::discard() { - if (mVertexBuffer) + if (!mVertexBuffer) { - void *dummy; - HRESULT result; - - result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); - if (FAILED(result)) - { - ERR("Discard lock failed with error 0x%08x", result); - return false; - } + return gl::Error(GL_OUT_OF_MEMORY, "Internal vertex buffer is not initialized."); + } - result = mVertexBuffer->Unlock(); - if (FAILED(result)) - { - ERR("Discard unlock failed with error 0x%08x", result); - return false; - } + void *dummy; + HRESULT result; - return true; + 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); } - else + + result = mVertexBuffer->Unlock(); + if (FAILED(result)) { - ERR("Vertex buffer not initialized."); - return false; + 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 @@ -199,11 +187,11 @@ IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const return mVertexBuffer; } -bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, - unsigned int *outSpaceRequired) +gl::Error VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, + unsigned int *outSpaceRequired) const { gl::VertexFormat vertexFormat(attrib, GL_FLOAT); - unsigned int elementSize = d3d9::GetVertexElementSize(vertexFormat); + const d3d9::VertexFormat &d3d9VertexInfo = d3d9::GetVertexFormatInfo(mRenderer->getCapsDeclTypes(), vertexFormat); if (attrib.enabled) { @@ -214,28 +202,21 @@ bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t } else { - if (static_cast(instances) < std::numeric_limits::max() - (attrib.divisor - 1)) - { - // Round up - elementCount = (static_cast(instances) + (attrib.divisor - 1)) / attrib.divisor; - } - else - { - elementCount = static_cast(instances) / attrib.divisor; - } + // Round up to divisor, if possible + elementCount = rx::UnsignedCeilDivide(static_cast(instances), attrib.divisor); } - if (elementSize <= std::numeric_limits::max() / elementCount) + if (d3d9VertexInfo.outputElementSize <= std::numeric_limits::max() / elementCount) { if (outSpaceRequired) { - *outSpaceRequired = elementSize * elementCount; + *outSpaceRequired = d3d9VertexInfo.outputElementSize * elementCount; } - return true; + return gl::Error(GL_NO_ERROR); } else { - return false; + return gl::Error(GL_OUT_OF_MEMORY, "New vertex buffer size would result in an overflow."); } } else @@ -245,7 +226,7 @@ bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t { *outSpaceRequired = elementSize * 4; } - return true; + 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 index fc4b6b6d26..bdcf4bb64a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h @@ -18,35 +18,35 @@ class Renderer9; class VertexBuffer9 : public VertexBuffer { public: - explicit VertexBuffer9(rx::Renderer9 *const renderer); + explicit VertexBuffer9(rx::Renderer9 *renderer); virtual ~VertexBuffer9(); - virtual bool initialize(unsigned int size, bool dynamicUsage); + virtual gl::Error initialize(unsigned int size, bool dynamicUsage); static VertexBuffer9 *makeVertexBuffer9(VertexBuffer *vertexBuffer); - virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, - GLint start, GLsizei count, GLsizei instances, unsigned int offset); + virtual gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int offset); - virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const; + virtual gl::Error getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const; virtual unsigned int getBufferSize() const; - virtual bool setBufferSize(unsigned int size); - virtual bool discard(); + virtual gl::Error setBufferSize(unsigned int size); + virtual gl::Error discard(); IDirect3DVertexBuffer9 *getBuffer() const; private: DISALLOW_COPY_AND_ASSIGN(VertexBuffer9); - rx::Renderer9 *const mRenderer; + rx::Renderer9 *mRenderer; IDirect3DVertexBuffer9 *mVertexBuffer; unsigned int mBufferSize; bool mDynamicUsage; - static bool spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, - unsigned int *outSpaceRequired); + gl::Error spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, + unsigned int *outSpaceRequired) const; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp index 303d8ad299..cefd786f11 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -7,11 +6,11 @@ // VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations. -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/VertexAttribute.h" -#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" #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 { @@ -41,13 +40,27 @@ VertexDeclarationCache::~VertexDeclarationCache() } } -GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw) +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 @@ -68,12 +81,14 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl } } - if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS) - { - return GL_INVALID_OPERATION; - } + // 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]; @@ -133,10 +148,11 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl } 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 = d3d9::GetNativeVertexFormat(vertexFormat); + element->Type = d3d9VertexInfo.nativeFormat; element->Method = D3DDECLMETHOD_DEFAULT; element->Usage = D3DDECLUSAGE_TEXCOORD; element->UsageIndex = programBinary->getSemanticIndex(i); @@ -172,7 +188,7 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl mLastSetVDecl = entry->vertexDeclaration; } - return GL_NO_ERROR; + return gl::Error(GL_NO_ERROR); } } @@ -194,12 +210,17 @@ GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Transl } memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)); - device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration); + 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_NO_ERROR; + return gl::Error(GL_NO_ERROR); } void VertexDeclarationCache::markStateDirty() diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h index 004e28df4f..9af36e0d7a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h @@ -9,6 +9,7 @@ #ifndef LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ #define LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ +#include "libGLESv2/Error.h" #include "libGLESv2/renderer/d3d/VertexDataManager.h" namespace gl @@ -25,7 +26,7 @@ class VertexDeclarationCache VertexDeclarationCache(); ~VertexDeclarationCache(); - GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw); + gl::Error applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw); void markStateDirty(); diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp index f5d1da62b3..f3acaf7987 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -18,255 +17,134 @@ namespace rx { -// 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) +namespace d3d9 { - UNREACHABLE(); -} const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z'))); const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L'))); -struct D3D9FormatInfo +struct D3D9FastCopyFormat { - D3DFORMAT mTexFormat; - D3DFORMAT mRenderFormat; - LoadImageFunction mLoadFunction; + GLenum destFormat; + GLenum destType; + ColorCopyFunction copyFunction; - D3D9FormatInfo() - : mTexFormat(D3DFMT_NULL), mRenderFormat(D3DFMT_NULL), mLoadFunction(NULL) + D3D9FastCopyFormat(GLenum destFormat, GLenum destType, ColorCopyFunction copyFunction) + : destFormat(destFormat), destType(destType), copyFunction(copyFunction) { } - D3D9FormatInfo(D3DFORMAT textureFormat, D3DFORMAT renderFormat, LoadImageFunction loadFunc) - : mTexFormat(textureFormat), mRenderFormat(renderFormat), mLoadFunction(loadFunc) - { } + bool operator<(const D3D9FastCopyFormat& other) const + { + return memcmp(this, &other, sizeof(D3D9FastCopyFormat)) < 0; + } }; -typedef std::pair D3D9FormatPair; -typedef std::map D3D9FormatMap; +typedef std::multimap D3D9FastCopyMap; -static D3D9FormatMap BuildD3D9FormatMap() +static D3D9FastCopyMap BuildFastCopyMap() { - D3D9FormatMap map; + D3D9FastCopyMap map; - // | Internal format | Texture format | Render format | Load function | - map.insert(D3D9FormatPair(GL_NONE, D3D9FormatInfo(D3DFMT_NULL, D3DFMT_NULL, UnreachableLoad ))); - - map.insert(D3D9FormatPair(GL_DEPTH_COMPONENT16, D3D9FormatInfo(D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ))); - map.insert(D3D9FormatPair(GL_DEPTH_COMPONENT32_OES, D3D9FormatInfo(D3DFMT_INTZ, D3DFMT_D32, UnreachableLoad ))); - map.insert(D3D9FormatPair(GL_DEPTH24_STENCIL8_OES, D3D9FormatInfo(D3DFMT_INTZ, D3DFMT_D24S8, UnreachableLoad ))); - map.insert(D3D9FormatPair(GL_STENCIL_INDEX8, D3D9FormatInfo(D3DFMT_UNKNOWN, D3DFMT_D24S8, UnreachableLoad ))); // TODO: What's the texture format? - - map.insert(D3D9FormatPair(GL_RGBA32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative ))); - map.insert(D3D9FormatPair(GL_RGB32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_A32B32G32R32F, LoadToNative3To4))); - map.insert(D3D9FormatPair(GL_RG32F_EXT, D3D9FormatInfo(D3DFMT_G32R32F, D3DFMT_G32R32F, LoadToNative ))); - map.insert(D3D9FormatPair(GL_R32F_EXT, D3D9FormatInfo(D3DFMT_R32F, D3DFMT_R32F, LoadToNative ))); - map.insert(D3D9FormatPair(GL_ALPHA32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadA32FToRGBA32F ))); - map.insert(D3D9FormatPair(GL_LUMINANCE32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadL32FToRGBA32F ))); - map.insert(D3D9FormatPair(GL_LUMINANCE_ALPHA32F_EXT, D3D9FormatInfo(D3DFMT_A32B32G32R32F, D3DFMT_UNKNOWN, LoadLA32FToRGBA32F ))); - - map.insert(D3D9FormatPair(GL_RGBA16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative ))); - map.insert(D3D9FormatPair(GL_RGB16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_A16B16G16R16F, LoadToNative3To4 ))); - map.insert(D3D9FormatPair(GL_RG16F_EXT, D3D9FormatInfo(D3DFMT_G16R16F, D3DFMT_G16R16F, LoadToNative ))); - map.insert(D3D9FormatPair(GL_R16F_EXT, D3D9FormatInfo(D3DFMT_R16F, D3DFMT_R16F, LoadToNative ))); - map.insert(D3D9FormatPair(GL_ALPHA16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadA16FToRGBA16F ))); - map.insert(D3D9FormatPair(GL_LUMINANCE16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadL16FToRGBA16F ))); - map.insert(D3D9FormatPair(GL_LUMINANCE_ALPHA16F_EXT, D3D9FormatInfo(D3DFMT_A16B16G16R16F, D3DFMT_UNKNOWN, LoadLA16FToRGBA16F ))); - - map.insert(D3D9FormatPair(GL_ALPHA8_EXT, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad))); - - map.insert(D3D9FormatPair(GL_RGB8_OES, D3D9FormatInfo(D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRGB8ToBGRX8 ))); - map.insert(D3D9FormatPair(GL_RGB565, D3D9FormatInfo(D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR5G6B5ToBGRA8 ))); - map.insert(D3D9FormatPair(GL_RGBA8_OES, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, FallbackLoad))); - map.insert(D3D9FormatPair(GL_RGBA4, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGBA4ToBGRA8 ))); - map.insert(D3D9FormatPair(GL_RGB5_A1, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadRGB5A1ToBGRA8 ))); - map.insert(D3D9FormatPair(GL_R8_EXT, D3D9FormatInfo(D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadR8ToBGRX8 ))); - map.insert(D3D9FormatPair(GL_RG8_EXT, D3D9FormatInfo(D3DFMT_X8R8G8B8, D3DFMT_X8R8G8B8, LoadRG8ToBGRX8 ))); - - map.insert(D3D9FormatPair(GL_BGRA8_EXT, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadToNative ))); - map.insert(D3D9FormatPair(GL_BGRA4_ANGLEX, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGRA4ToBGRA8 ))); - map.insert(D3D9FormatPair(GL_BGR5_A1_ANGLEX, D3D9FormatInfo(D3DFMT_A8R8G8B8, D3DFMT_A8R8G8B8, LoadBGR5A1ToBGRA8 ))); - - map.insert(D3D9FormatPair(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, D3D9FormatInfo(D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> ))); - map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, D3D9FormatInfo(D3DFMT_DXT1, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 8> ))); - map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, D3D9FormatInfo(D3DFMT_DXT3, D3DFMT_UNKNOWN, LoadCompressedToNative<4, 4, 16> ))); - map.insert(D3D9FormatPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, D3D9FormatInfo(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. - map.insert(D3D9FormatPair(GL_LUMINANCE8_EXT, D3D9FormatInfo(D3DFMT_L8, D3DFMT_UNKNOWN, LoadToNative ))); - map.insert(D3D9FormatPair(GL_LUMINANCE8_ALPHA8_EXT, D3D9FormatInfo(D3DFMT_A8L8, D3DFMT_UNKNOWN, LoadToNative ))); + map.insert(std::make_pair(D3DFMT_A8R8G8B8, D3D9FastCopyFormat(GL_RGBA, GL_UNSIGNED_BYTE, CopyBGRA8ToRGBA8))); return map; } -static bool GetD3D9FormatInfo(GLenum internalFormat, D3D9FormatInfo *outFormatInfo) +// 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() { - static const D3D9FormatMap formatMap = BuildD3D9FormatMap(); - D3D9FormatMap::const_iterator iter = formatMap.find(internalFormat); - if (iter != formatMap.end()) - { - if (outFormatInfo) - { - *outFormatInfo = iter->second; - } - return true; - } - else - { - return false; - } } -// A map to determine the pixel size and mip generation function of a given D3D format -struct D3DFormatInfo +ColorCopyFunction D3DFormat::getFastCopyFunction(GLenum format, GLenum type) const { - GLuint mPixelBits; - GLuint mBlockWidth; - GLuint mBlockHeight; - GLenum mInternalFormat; - - MipGenerationFunction mMipGenerationFunction; - ColorReadFunction mColorReadFunction; + FastCopyFunctionMap::const_iterator iter = fastCopyFunctions.find(std::make_pair(format, type)); + return (iter != fastCopyFunctions.end()) ? iter->second : NULL; +} - D3DFormatInfo() - : mPixelBits(0), mBlockWidth(0), mBlockHeight(0), mInternalFormat(GL_NONE), mMipGenerationFunction(NULL), - mColorReadFunction(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; - D3DFormatInfo(GLuint pixelBits, GLuint blockWidth, GLuint blockHeight, GLenum internalFormat, - MipGenerationFunction mipFunc, ColorReadFunction readFunc) - : mPixelBits(pixelBits), mBlockWidth(blockWidth), mBlockHeight(blockHeight), mInternalFormat(internalFormat), - mMipGenerationFunction(mipFunc), mColorReadFunction(readFunc) - { } -}; + 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)); + } -typedef std::pair D3D9FormatInfoPair; -typedef std::map D3D9FormatInfoMap; + map->insert(std::make_pair(format, info)); +} static D3D9FormatInfoMap BuildD3D9FormatInfoMap() { D3D9FormatInfoMap map; - // | D3DFORMAT | | S |W |H | Internal format | Mip generation function | Color read function | - map.insert(D3D9FormatInfoPair(D3DFMT_NULL, D3DFormatInfo( 0, 0, 0, GL_NONE, NULL, NULL ))); - map.insert(D3D9FormatInfoPair(D3DFMT_UNKNOWN, D3DFormatInfo( 0, 0, 0, GL_NONE, NULL, NULL ))); - - map.insert(D3D9FormatInfoPair(D3DFMT_L8, D3DFormatInfo( 8, 1, 1, GL_LUMINANCE8_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_A8, D3DFormatInfo( 8, 1, 1, GL_ALPHA8_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_A8L8, D3DFormatInfo( 16, 1, 1, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_A4R4G4B4, D3DFormatInfo( 16, 1, 1, GL_BGRA4_ANGLEX, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_A1R5G5B5, D3DFormatInfo( 16, 1, 1, GL_BGR5_A1_ANGLEX, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_R5G6B5, D3DFormatInfo( 16, 1, 1, GL_RGB565, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_X8R8G8B8, D3DFormatInfo( 32, 1, 1, GL_BGRA8_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_A8R8G8B8, D3DFormatInfo( 32, 1, 1, GL_BGRA8_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_R16F, D3DFormatInfo( 16, 1, 1, GL_R16F_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_G16R16F, D3DFormatInfo( 32, 1, 1, GL_RG16F_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_A16B16G16R16F, D3DFormatInfo( 64, 1, 1, GL_RGBA16F_EXT, GenerateMip, ReadColor))); - map.insert(D3D9FormatInfoPair(D3DFMT_R32F, D3DFormatInfo( 32, 1, 1, GL_R32F_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_G32R32F, D3DFormatInfo( 64, 1, 1, GL_RG32F_EXT, GenerateMip, ReadColor ))); - map.insert(D3D9FormatInfoPair(D3DFMT_A32B32G32R32F, D3DFormatInfo(128, 1, 1, GL_RGBA32F_EXT, GenerateMip, ReadColor))); - - map.insert(D3D9FormatInfoPair(D3DFMT_D16, D3DFormatInfo( 16, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL ))); - map.insert(D3D9FormatInfoPair(D3DFMT_D24S8, D3DFormatInfo( 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL ))); - map.insert(D3D9FormatInfoPair(D3DFMT_D24X8, D3DFormatInfo( 32, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL ))); - map.insert(D3D9FormatInfoPair(D3DFMT_D32, D3DFormatInfo( 32, 1, 1, GL_DEPTH_COMPONENT32_OES, NULL, NULL ))); - - map.insert(D3D9FormatInfoPair(D3DFMT_INTZ, D3DFormatInfo( 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL ))); - - map.insert(D3D9FormatInfoPair(D3DFMT_DXT1, D3DFormatInfo( 64, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL, NULL ))); - map.insert(D3D9FormatInfoPair(D3DFMT_DXT3, D3DFormatInfo(128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL, NULL ))); - map.insert(D3D9FormatInfoPair(D3DFMT_DXT5, D3DFormatInfo(128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL, NULL ))); + // | 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; } -static const D3D9FormatInfoMap &GetD3D9FormatInfoMap() +const D3DFormat &GetD3DFormatInfo(D3DFORMAT format) { static const D3D9FormatInfoMap infoMap = BuildD3D9FormatInfoMap(); - return infoMap; -} - -static bool GetD3D9FormatInfo(D3DFORMAT format, D3DFormatInfo *outFormatInfo) -{ - const D3D9FormatInfoMap &infoMap = GetD3D9FormatInfoMap(); D3D9FormatInfoMap::const_iterator iter = infoMap.find(format); if (iter != infoMap.end()) { - if (outFormatInfo) - { - *outFormatInfo = iter->second; - } - return true; + return iter->second; } else { - return false; + static const D3DFormat defaultInfo; + return defaultInfo; } } -static d3d9::D3DFormatSet BuildAllD3DFormatSet() -{ - d3d9::D3DFormatSet set; - - const D3D9FormatInfoMap &infoMap = GetD3D9FormatInfoMap(); - for (D3D9FormatInfoMap::const_iterator i = infoMap.begin(); i != infoMap.end(); ++i) - { - set.insert(i->first); - } - - return set; -} - -struct D3D9FastCopyFormat -{ - D3DFORMAT mSourceFormat; - GLenum mDestFormat; - GLenum mDestType; - - D3D9FastCopyFormat(D3DFORMAT sourceFormat, GLenum destFormat, GLenum destType) - : mSourceFormat(sourceFormat), mDestFormat(destFormat), mDestType(destType) - { } - - bool operator<(const D3D9FastCopyFormat& other) const - { - return memcmp(this, &other, sizeof(D3D9FastCopyFormat)) < 0; - } -}; -typedef std::map D3D9FastCopyMap; -typedef std::pair D3D9FastCopyPair; -static D3D9FastCopyMap BuildFastCopyMap() -{ - D3D9FastCopyMap map; - - map.insert(D3D9FastCopyPair(D3D9FastCopyFormat(D3DFMT_A8R8G8B8, GL_RGBA, GL_UNSIGNED_BYTE), CopyBGRAUByteToRGBAUByte)); - - return map; -} typedef std::pair InternalFormatInitialzerPair; typedef std::map InternalFormatInitialzerMap; @@ -275,160 +153,148 @@ static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap() { InternalFormatInitialzerMap map; - map.insert(InternalFormatInitialzerPair(GL_RGB16F, Initialize4ComponentData)); - map.insert(InternalFormatInitialzerPair(GL_RGB32F, Initialize4ComponentData)); + map.insert(InternalFormatInitialzerPair(GL_RGB16F, Initialize4ComponentData)); + map.insert(InternalFormatInitialzerPair(GL_RGB32F, Initialize4ComponentData)); return map; } -static const InternalFormatInitialzerMap &GetInternalFormatInitialzerMap() -{ - static const InternalFormatInitialzerMap map = BuildInternalFormatInitialzerMap(); - 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. -namespace d3d9 -{ +typedef bool(*FallbackPredicateFunction)(); -MipGenerationFunction GetMipGenerationFunction(D3DFORMAT format) +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) { - D3DFormatInfo d3dFormatInfo; - if (GetD3D9FormatInfo(format, &d3dFormatInfo)) + if (pred()) { - return d3dFormatInfo.mMipGenerationFunction; + prefered(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); } else { - UNREACHABLE(); - return NULL; + fallback(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); } } -LoadImageFunction GetImageLoadFunction(GLenum internalFormat) +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) { - D3D9FormatInfo d3d9FormatInfo; - if (GetD3D9FormatInfo(internalFormat, &d3d9FormatInfo)) - { - return d3d9FormatInfo.mLoadFunction; - } - else - { - UNREACHABLE(); - return NULL; - } + UNREACHABLE(); } -GLuint GetFormatPixelBytes(D3DFORMAT format) -{ - D3DFormatInfo d3dFormatInfo; - if (GetD3D9FormatInfo(format, &d3dFormatInfo)) - { - return d3dFormatInfo.mPixelBits / 8; - } - else - { - UNREACHABLE(); - return 0; - } -} +typedef std::pair D3D9FormatPair; +typedef std::map D3D9FormatMap; -GLuint GetBlockWidth(D3DFORMAT format) +TextureFormat::TextureFormat() + : texFormat(D3DFMT_NULL), + renderFormat(D3DFMT_NULL), + dataInitializerFunction(NULL), + loadFunction(UnreachableLoad) { - D3DFormatInfo d3dFormatInfo; - if (GetD3D9FormatInfo(format, &d3dFormatInfo)) - { - return d3dFormatInfo.mBlockWidth; - } - else - { - UNREACHABLE(); - return 0; - } } -GLuint GetBlockHeight(D3DFORMAT format) +static inline void InsertD3D9FormatInfo(D3D9FormatMap *map, GLenum internalFormat, D3DFORMAT texFormat, + D3DFORMAT renderFormat, LoadImageFunction loadFunction) { - D3DFormatInfo d3dFormatInfo; - if (GetD3D9FormatInfo(format, &d3dFormatInfo)) - { - return d3dFormatInfo.mBlockHeight; - } - else - { - UNREACHABLE(); - return 0; - } -} + TextureFormat info; + info.texFormat = texFormat; + info.renderFormat = renderFormat; -GLuint GetBlockSize(D3DFORMAT format, GLuint width, GLuint height) -{ - D3DFormatInfo d3dFormatInfo; - if (GetD3D9FormatInfo(format, &d3dFormatInfo)) - { - GLuint numBlocksWide = (width + d3dFormatInfo.mBlockWidth - 1) / d3dFormatInfo.mBlockWidth; - GLuint numBlocksHight = (height + d3dFormatInfo.mBlockHeight - 1) / d3dFormatInfo.mBlockHeight; + static const InternalFormatInitialzerMap dataInitializationMap = BuildInternalFormatInitialzerMap(); + InternalFormatInitialzerMap::const_iterator dataInitIter = dataInitializationMap.find(internalFormat); + info.dataInitializerFunction = (dataInitIter != dataInitializationMap.end()) ? dataInitIter->second : NULL; - return (d3dFormatInfo.mPixelBits * numBlocksWide * numBlocksHight) / 8; - } - else - { - UNREACHABLE(); - return 0; - } + info.loadFunction = loadFunction; + + map->insert(std::make_pair(internalFormat, info)); } -void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) +static D3D9FormatMap BuildD3D9FormatMap() { - D3DFormatInfo d3dFormatInfo; - if (GetD3D9FormatInfo(format, &d3dFormatInfo)) - { - int upsampleCount = 0; + D3D9FormatMap map; - GLsizei blockWidth = d3dFormatInfo.mBlockWidth; - GLsizei blockHeight = d3dFormatInfo.mBlockHeight; + // | 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> ); - // Don't expand the size of full textures that are at least (blockWidth x blockHeight) already. - if (isImage || *requestWidth < blockWidth || *requestHeight < blockHeight) - { - while (*requestWidth % blockWidth != 0 || *requestHeight % blockHeight != 0) - { - *requestWidth <<= 1; - *requestHeight <<= 1; - upsampleCount++; - } - } - *levelOffset = upsampleCount; - } -} + // 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 ); -const D3DFormatSet &GetAllUsedD3DFormats() -{ - static const D3DFormatSet formatSet = BuildAllD3DFormatSet(); - return formatSet; + return map; } -ColorReadFunction GetColorReadFunction(D3DFORMAT format) +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat) { - D3DFormatInfo d3dFormatInfo; - if (GetD3D9FormatInfo(format, &d3dFormatInfo)) + static const D3D9FormatMap formatMap = BuildD3D9FormatMap(); + D3D9FormatMap::const_iterator iter = formatMap.find(internalFormat); + if (iter != formatMap.end()) { - return d3dFormatInfo.mColorReadFunction; + return iter->second; } else { - UNREACHABLE(); - return NULL; + static const TextureFormat defaultInfo; + return defaultInfo; } } -ColorCopyFunction GetFastCopyFunction(D3DFORMAT sourceFormat, GLenum destFormat, GLenum destType) -{ - static const D3D9FastCopyMap fastCopyMap = BuildFastCopyMap(); - D3D9FastCopyMap::const_iterator iter = fastCopyMap.find(D3D9FastCopyFormat(sourceFormat, destFormat, destType)); - return (iter != fastCopyMap.end()) ? iter->second : NULL; -} - -GLenum GetDeclTypeComponentType(D3DDECLTYPE declType) +static GLenum GetDeclTypeComponentType(D3DDECLTYPE declType) { switch (declType) { @@ -451,27 +317,13 @@ GLenum GetDeclTypeComponentType(D3DDECLTYPE declType) // Attribute format conversion enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; -struct FormatConverter -{ - bool identity; - std::size_t outputElementSize; - void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out); - D3DDECLTYPE d3dDeclType; -}; - struct TranslationDescription { DWORD capsFlag; - FormatConverter preferredConversion; - FormatConverter fallbackConversion; + VertexFormat preferredConversion; + VertexFormat fallbackConversion; }; -static unsigned int typeIndex(GLenum type); -static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute); - -bool mTranslationsInitialized = false; -FormatConverter mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; - // Mapping from OpenGL-ES vertex attrib type to D3D decl type: // // BYTE SHORT (Cast) @@ -623,14 +475,35 @@ public: 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) \ { \ @@ -651,168 +524,63 @@ public: { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ } -const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1] +static inline unsigned int ComputeTypeIndex(GLenum type) { - 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) -}; + 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; -void InitializeVertexTranslations(const rx::Renderer9 *renderer) -{ - DWORD declTypes = renderer->getCapsDeclTypes(); + default: UNREACHABLE(); return 5; + } +} - for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++) +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) { - for (unsigned int j = 0; j < 2; j++) + const TranslationDescription translations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1] { - for (unsigned int k = 0; k < 4; k++) + 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++) { - if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0) - { - mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion; - } - else + for (unsigned int k = 0; k < 4; k++) { - mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion; + 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; } -} - -unsigned int typeIndex(GLenum type) -{ - switch (type) - { - case GL_BYTE: return 0; - case GL_UNSIGNED_BYTE: return 1; - case GL_SHORT: return 2; - case GL_UNSIGNED_SHORT: return 3; - case GL_FIXED: return 4; - case GL_FLOAT: return 5; - default: UNREACHABLE(); return 5; - } -} + ASSERT(intializedDeclTypes == supportedDeclTypes); -const FormatConverter &formatConverter(const gl::VertexFormat &vertexFormat) -{ // Pure integer attributes only supported in ES3.0 ASSERT(!vertexFormat.mPureInteger); - return mFormatConverters[typeIndex(vertexFormat.mType)][vertexFormat.mNormalized][vertexFormat.mComponents - 1]; -} - -VertexCopyFunction GetVertexCopyFunction(const gl::VertexFormat &vertexFormat) -{ - return formatConverter(vertexFormat).convertArray; -} - -size_t GetVertexElementSize(const gl::VertexFormat &vertexFormat) -{ - return formatConverter(vertexFormat).outputElementSize; -} - -VertexConversionType GetVertexConversionType(const gl::VertexFormat &vertexFormat) -{ - return (formatConverter(vertexFormat).identity ? VERTEX_CONVERT_NONE : VERTEX_CONVERT_CPU); -} - -D3DDECLTYPE GetNativeVertexFormat(const gl::VertexFormat &vertexFormat) -{ - return formatConverter(vertexFormat).d3dDeclType; -} - -} - -namespace gl_d3d9 -{ - -D3DFORMAT GetTextureFormat(GLenum internalFormat) -{ - D3D9FormatInfo d3d9FormatInfo; - if (GetD3D9FormatInfo(internalFormat, &d3d9FormatInfo)) - { - return d3d9FormatInfo.mTexFormat; - } - else - { - return D3DFMT_UNKNOWN; - } -} - -D3DFORMAT GetRenderFormat(GLenum internalFormat) -{ - D3D9FormatInfo d3d9FormatInfo; - if (GetD3D9FormatInfo(internalFormat, &d3d9FormatInfo)) - { - return d3d9FormatInfo.mRenderFormat; - } - else - { - return D3DFMT_UNKNOWN; - } -} - -D3DMULTISAMPLE_TYPE GetMultisampleType(GLsizei samples) -{ - return (samples > 1) ? static_cast(samples) : D3DMULTISAMPLE_NONE; -} - -bool RequiresTextureDataInitialization(GLint internalFormat) -{ - const InternalFormatInitialzerMap &map = GetInternalFormatInitialzerMap(); - return map.find(internalFormat) != map.end(); -} - -InitializeTextureDataFunction GetTextureDataInitializationFunction(GLint internalFormat) -{ - const InternalFormatInitialzerMap &map = GetInternalFormatInitialzerMap(); - InternalFormatInitialzerMap::const_iterator iter = map.find(internalFormat); - if (iter != map.end()) - { - return iter->second; - } - else - { - UNREACHABLE(); - return NULL; - } -} - -} - -namespace d3d9_gl -{ - -GLenum GetInternalFormat(D3DFORMAT format) -{ - static const D3D9FormatInfoMap infoMap = BuildD3D9FormatInfoMap(); - D3D9FormatInfoMap::const_iterator iter = infoMap.find(format); - if (iter != infoMap.end()) - { - return iter->second.mInternalFormat; - } - else - { - UNREACHABLE(); - return GL_NONE; - } -} - -GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type) -{ - return (type != D3DMULTISAMPLE_NONMASKABLE) ? type : 0; -} - -bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format) -{ - GLenum internalFormat = d3d9_gl::GetInternalFormat(d3dformat); - GLenum convertedFormat = gl::GetFormat(internalFormat); - return convertedFormat == format; + 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 index 26388794e0..f26fe43b36 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h @@ -12,6 +12,8 @@ #include "libGLESv2/formatutils.h" +#include + namespace rx { @@ -20,55 +22,50 @@ class Renderer9; namespace d3d9 { -typedef std::set D3DFormatSet; - -MipGenerationFunction GetMipGenerationFunction(D3DFORMAT format); -LoadImageFunction GetImageLoadFunction(GLenum internalFormat); - -GLuint GetFormatPixelBytes(D3DFORMAT format); -GLuint GetBlockWidth(D3DFORMAT format); -GLuint GetBlockHeight(D3DFORMAT format); -GLuint GetBlockSize(D3DFORMAT format, GLuint width, GLuint height); +typedef std::map, ColorCopyFunction> FastCopyFunctionMap; -void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); - -const D3DFormatSet &GetAllUsedD3DFormats(); +struct D3DFormat +{ + D3DFormat(); -ColorReadFunction GetColorReadFunction(D3DFORMAT format); -ColorCopyFunction GetFastCopyFunction(D3DFORMAT sourceFormat, GLenum destFormat, GLenum destType); + GLuint pixelBytes; + GLuint blockWidth; + GLuint blockHeight; -VertexCopyFunction GetVertexCopyFunction(const gl::VertexFormat &vertexFormat); -size_t GetVertexElementSize(const gl::VertexFormat &vertexFormat); -VertexConversionType GetVertexConversionType(const gl::VertexFormat &vertexFormat); -D3DDECLTYPE GetNativeVertexFormat(const gl::VertexFormat &vertexFormat); + GLenum internalFormat; -GLenum GetDeclTypeComponentType(D3DDECLTYPE declType); -int GetDeclTypeComponentCount(D3DDECLTYPE declType); -bool IsDeclTypeNormalized(D3DDECLTYPE declType); + MipGenerationFunction mipGenerationFunction; + ColorReadFunction colorReadFunction; -void InitializeVertexTranslations(const rx::Renderer9 *renderer); + FastCopyFunctionMap fastCopyFunctions; + ColorCopyFunction getFastCopyFunction(GLenum format, GLenum type) const; +}; +const D3DFormat &GetD3DFormatInfo(D3DFORMAT format); -} - -namespace gl_d3d9 +struct VertexFormat { + VertexFormat(); -D3DFORMAT GetTextureFormat(GLenum internalForma); -D3DFORMAT GetRenderFormat(GLenum internalFormat); + VertexConversionType conversionType; + size_t outputElementSize; + VertexCopyFunction copyFunction; + D3DDECLTYPE nativeFormat; + GLenum componentType; +}; +const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::VertexFormat &vertexFormat); -D3DMULTISAMPLE_TYPE GetMultisampleType(GLsizei samples); +struct TextureFormat +{ + TextureFormat(); -bool RequiresTextureDataInitialization(GLint internalFormat); -InitializeTextureDataFunction GetTextureDataInitializationFunction(GLint internalFormat); + D3DFORMAT texFormat; + D3DFORMAT renderFormat; -} - -namespace d3d9_gl -{ + InitializeTextureDataFunction dataInitializerFunction; -GLenum GetInternalFormat(D3DFORMAT format); -GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type); -bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format); + LoadImageFunction loadFunction; +}; +const TextureFormat &GetTextureFormatInfo(GLenum internalFormat); } 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 index 68e5378fbb..e7a91e62d6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -11,9 +10,10 @@ #include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" #include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" #include "libGLESv2/formatutils.h" -#include "common/mathutil.h" -#include "libGLESv2/Context.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" @@ -246,40 +246,55 @@ void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DT } } +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; - D3DFORMAT renderFormat = gl_d3d9::GetRenderFormat(internalFormat); - if (gl::GetDepthBits(internalFormat) > 0 || gl::GetStencilBits(internalFormat) > 0) + 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, renderFormat)); - textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, renderFormat)); - textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, renderFormat)) || - SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, renderFormat)); + textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)); } else { - D3DFORMAT textureFormat = gl_d3d9::GetTextureFormat(internalFormat); - textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, textureFormat)) && - SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_CUBETEXTURE, textureFormat)); - textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, textureFormat)); - textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, textureFormat)) || - SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, textureFormat)); + 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, renderFormat, TRUE, multisampleType, NULL); + HRESULT result = d3d9->CheckDeviceMultiSampleType(adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, NULL); if (SUCCEEDED(result)) { textureCaps.sampleCounts.insert(i); @@ -302,12 +317,20 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT 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 @@ -347,6 +370,77 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT 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; + + const size_t MAX_VERTEX_OUTPUT_VECTORS_SM3 = 10; + const size_t MAX_VERTEX_OUTPUT_VECTORS_SM2 = 8; + 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); @@ -394,6 +488,7 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT 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; @@ -406,4 +501,42 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT } +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; +} + +RenderTarget9 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment) +{ + RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment); + return RenderTarget9::makeRenderTarget9(renderTarget); +} + +} + } 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 index 7f3c65d3e0..b0a940e60a 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h @@ -4,7 +4,7 @@ // found in the LICENSE file. // -// renderer9_utils.h: Conversion functions and other utility routines +// renderer9_utils.h: Conversion functions and other utility routines // specific to the D3D9 renderer #ifndef LIBGLESV2_RENDERER_RENDERER9_UTILS_H @@ -13,8 +13,14 @@ #include "libGLESv2/angletypes.h" #include "libGLESv2/Caps.h" +namespace gl +{ +class FramebufferAttachment; +} + namespace rx { +class RenderTarget9; namespace gl_d3d9 { @@ -31,11 +37,17 @@ 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); @@ -44,6 +56,10 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT 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) @@ -58,6 +74,8 @@ inline bool isDeviceLostError(HRESULT errorCode) } } +RenderTarget9 *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment); + } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp index 4a294608ae..1986191a75 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp index dcf347d421..f777b30be6 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h b/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h index 590b9d48a3..81ba8a0767 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h @@ -10,6 +10,10 @@ #ifndef LIBGLESV2_VERTEXCONVERSION_H_ #define LIBGLESV2_VERTEXCONVERSION_H_ +#include +#include +#include + namespace rx { @@ -154,11 +158,13 @@ struct VertexDataConverter static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity; static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType); - static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out) + 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 = pointerAddBytes(in, i * stride); + const InputType *ein = reinterpret_cast(input + i * stride); copyComponent(out, ein, 0, static_cast(DefaultValueRule::zero())); copyComponent(out, ein, 1, static_cast(DefaultValueRule::zero())); @@ -169,19 +175,7 @@ struct VertexDataConverter } } - static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out) - { - return convertArray(static_cast(in), stride, n, static_cast(out)); - } - private: - // Advance the given pointer by a number of bytes (not pointed-to elements). - template - static T *pointerAddBytes(T *basePtr, std::size_t numBytes) - { - return reinterpret_cast(reinterpret_cast(basePtr) + numBytes); - } - static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue) { if (WidenRule::finalWidth > elementindex) diff --git a/src/3rdparty/angle/src/libGLESv2/validationES.cpp b/src/3rdparty/angle/src/libGLESv2/validationES.cpp index 309c4daedb..f79bc97e4f 100644 --- a/src/3rdparty/angle/src/libGLESv2/validationES.cpp +++ b/src/3rdparty/angle/src/libGLESv2/validationES.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -20,6 +19,7 @@ #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" @@ -168,7 +168,7 @@ bool ValidMipLevel(const Context *context, GLenum target, GLint level) return level <= gl::log2(maxDimension); } -bool ValidImageSize(const gl::Context *context, GLenum target, GLint level, +bool ValidImageSize(const Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth) { if (level < 0 || width < 0 || height < 0 || depth < 0) @@ -190,17 +190,16 @@ bool ValidImageSize(const gl::Context *context, GLenum target, GLint level, return true; } -bool ValidCompressedImageSize(const gl::Context *context, GLenum internalFormat, GLsizei width, GLsizei height) +bool ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLsizei width, GLsizei height) { - if (!IsFormatCompressed(internalFormat)) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat); + if (!formatInfo.compressed) { return false; } - GLint blockWidth = GetCompressedBlockWidth(internalFormat); - GLint blockHeight = GetCompressedBlockHeight(internalFormat); - if (width < 0 || (width > blockWidth && width % blockWidth != 0) || - height < 0 || (height > blockHeight && height % blockHeight != 0)) + 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; } @@ -225,7 +224,7 @@ bool ValidQueryType(const Context *context, GLenum queryType) } } -bool ValidProgram(const Context *context, GLuint id) +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 @@ -238,16 +237,18 @@ bool ValidProgram(const Context *context, GLuint id) else if (context->getShader(id) != NULL) { // ID is the wrong type - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } else { // No shader/program object has this ID - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } -bool ValidateAttachmentTarget(const gl::Context *context, GLenum attachment) +bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment) { if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) { @@ -255,7 +256,8 @@ bool ValidateAttachmentTarget(const gl::Context *context, GLenum attachment) if (colorAttachment >= context->getCaps().maxColorAttachments) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } else @@ -269,19 +271,21 @@ bool ValidateAttachmentTarget(const gl::Context *context, GLenum attachment) case GL_DEPTH_STENCIL_ATTACHMENT: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } return true; } -bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum target, GLsizei samples, +bool ValidateRenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, bool angleExtension) { @@ -290,43 +294,44 @@ bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum ta case GL_RENDERBUFFER: break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (width < 0 || height < 0 || samples < 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } - if (!gl::IsValidInternalFormat(internalformat, context->getExtensions(), context->getClientVersion())) + const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); + if (!formatCaps.renderable) { - return gl::error(GL_INVALID_ENUM, false); + 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. - if (!gl::IsSizedInternalFormat(internalformat)) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + if (formatInfo.pixelBytes == 0) { - return gl::error(GL_INVALID_ENUM, false); - } - - GLenum componentType = gl::GetComponentType(internalformat); - if ((componentType == GL_UNSIGNED_INT || componentType == GL_INT) && samples > 0) - { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } - const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); - if (!formatCaps.renderable) + if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (static_cast(std::max(width, height)) > context->getCaps().maxRenderbufferSize) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal @@ -335,23 +340,34 @@ bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum ta // internal format. if (angleExtension) { - if (samples > context->getMaxSupportedSamples()) + ASSERT(context->getExtensions().framebufferMultisample); + if (static_cast(samples) > context->getExtensions().maxSamples) { - return gl::error(GL_INVALID_VALUE, false); + 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 (samples > context->getMaxSupportedFormatSamples(internalformat)) + if (static_cast(samples) > formatCaps.getMaxSamples()) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } GLuint handle = context->getState().getRenderbufferId(); if (handle == 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } return true; @@ -362,7 +378,8 @@ bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum targ { if (!ValidFramebufferTarget(target)) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); @@ -370,7 +387,8 @@ bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum targ if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (!ValidateAttachmentTarget(context, attachment)) @@ -386,7 +404,8 @@ bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum targ { if (!context->getRenderbuffer(renderbuffer)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -428,16 +447,19 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint case GL_LINEAR: if (fromAngleExtension) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (mask == 0) @@ -450,14 +472,16 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)) { ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."); - return gl::error(GL_INVALID_OPERATION, false); + 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) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (context->getState().getReadFramebuffer()->id() == context->getState().getDrawFramebuffer()->id()) @@ -467,7 +491,8 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint ERR("Blits with the same source and destination framebuffer are not supported by this " "implementation."); } - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } gl::Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); @@ -475,12 +500,14 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE || !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; } if (drawFramebuffer->getSamples() != 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1; @@ -493,45 +520,50 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint if (readColorBuffer && drawColorBuffer) { GLenum readInternalFormat = readColorBuffer->getActualFormat(); - GLenum readComponentType = gl::GetComponentType(readInternalFormat); + 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(); - GLenum drawComponentType = gl::GetComponentType(drawInternalFormat); + 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 ( (readComponentType == GL_UNSIGNED_NORMALIZED || readComponentType == GL_SIGNED_NORMALIZED) && - !(drawComponentType == GL_UNSIGNED_NORMALIZED || drawComponentType == GL_SIGNED_NORMALIZED)) + if ( (readFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || readFormatInfo.componentType == GL_SIGNED_NORMALIZED) && + !(drawFormatInfo.componentType == GL_UNSIGNED_NORMALIZED || drawFormatInfo.componentType == GL_SIGNED_NORMALIZED)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (readComponentType == GL_UNSIGNED_INT && drawComponentType != GL_UNSIGNED_INT) + if (readFormatInfo.componentType == GL_UNSIGNED_INT && drawFormatInfo.componentType != GL_UNSIGNED_INT) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (readComponentType == GL_INT && drawComponentType != GL_INT) + if (readFormatInfo.componentType == GL_INT && drawFormatInfo.componentType != GL_INT) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } } - if ((readComponentType == GL_INT || readComponentType == GL_UNSIGNED_INT) && filter == GL_LINEAR) + if ((readFormatInfo.componentType == GL_INT || readFormatInfo.componentType == GL_UNSIGNED_INT) && filter == GL_LINEAR) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (fromAngleExtension) @@ -539,7 +571,8 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType(); if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) @@ -551,12 +584,14 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint if (attachment->type() != GL_TEXTURE_2D && attachment->type() != GL_RENDERBUFFER) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (attachment->getActualFormat() != readColorBuffer->getActualFormat()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } } @@ -564,7 +599,8 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } } @@ -579,12 +615,14 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint { if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (readDepthBuffer->getSamples() > 0 && !sameBounds) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (fromAngleExtension) @@ -593,12 +631,14 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) { ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); - return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted + context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted + return false; } if (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } } @@ -613,12 +653,14 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint { if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (readStencilBuffer->getSamples() > 0 && !sameBounds) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (fromAngleExtension) @@ -627,12 +669,14 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) { ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); - return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted + context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted + return false; } if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } } @@ -641,7 +685,7 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint return true; } -bool ValidateGetVertexAttribParameters(GLenum pname, int clientVersion) +bool ValidateGetVertexAttribParameters(Context *context, GLenum pname) { switch (pname) { @@ -661,10 +705,16 @@ bool ValidateGetVertexAttribParameters(GLenum pname, int clientVersion) return true; case GL_VERTEX_ATTRIB_ARRAY_INTEGER: - return ((clientVersion >= 3) ? true : gl::error(GL_INVALID_ENUM, false)); + if (context->getClientVersion() < 3) + { + context->recordError(Error(GL_INVALID_ENUM)); + return false; + } + return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } @@ -685,7 +735,8 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_TEXTURE_MAX_LOD: if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; @@ -704,7 +755,8 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_MIRRORED_REPEAT: return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } case GL_TEXTURE_MIN_FILTER: @@ -718,7 +770,8 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_LINEAR_MIPMAP_LINEAR: return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; @@ -729,7 +782,8 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_LINEAR: return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; @@ -740,20 +794,23 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_FRAMEBUFFER_ATTACHMENT_ANGLE: return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_TEXTURE_MAX_ANISOTROPY_EXT: if (!context->getExtensions().textureFilterAnisotropic) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } // we assume the parameter passed to this validation method is truncated, not rounded if (param < 1) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } return true; @@ -770,7 +827,8 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_COMPARE_REF_TO_TEXTURE: return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; @@ -788,7 +846,8 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_NEVER: return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; @@ -806,7 +865,8 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_ONE: return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; @@ -814,16 +874,18 @@ bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) case GL_TEXTURE_MAX_LEVEL: if (param < 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } -bool ValidateSamplerObjectParameter(GLenum pname) +bool ValidateSamplerObjectParameter(gl::Context *context, GLenum pname) { switch (pname) { @@ -839,7 +901,8 @@ bool ValidateSamplerObjectParameter(GLenum pname) return true; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } @@ -851,17 +914,20 @@ bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsize if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; } if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (!framebuffer->getReadColorbuffer()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } GLenum currentInternalFormat, currentFormat, currentType; @@ -874,20 +940,22 @@ bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsize if (!(currentFormat == format && currentType == type) && !validReadFormat) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - GLenum sizedInternalFormat = IsSizedInternalFormat(format) ? format - : GetSizedInternalFormat(format, type); + GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); + const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat); - GLsizei outputPitch = GetRowPitch(sizedInternalFormat, type, width, context->getState().getPackAlignment()); + GLsizei outputPitch = sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment()); // sized query sanity check if (bufSize) { int requiredSize = outputPitch * height; if (requiredSize > *bufSize) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -898,12 +966,14 @@ bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id) { if (!ValidQueryType(context, target)) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (id == 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an @@ -923,7 +993,8 @@ bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id) // no query may be active for either if glBeginQuery targets either. if (context->getState().isQueryActive()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } Query *queryObject = context->getQuery(id, true, target); @@ -931,13 +1002,15 @@ bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id) // check that name was obtained with glGenQueries if (!queryObject) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } // check for type mismatch if (queryObject->getType() != target) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } return true; @@ -947,19 +1020,16 @@ bool ValidateEndQuery(gl::Context *context, GLenum target) { if (!ValidQueryType(context, target)) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } const Query *queryObject = context->getState().getActiveQuery(target); if (queryObject == NULL) { - return gl::error(GL_INVALID_OPERATION, false); - } - - if (!queryObject->isStarted()) - { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } return true; @@ -970,13 +1040,15 @@ static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniform { if (count < 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); if (!programBinary) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (location == -1) @@ -987,7 +1059,8 @@ static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniform if (!programBinary->isValidUniformLocation(location)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } LinkedUniform *uniform = programBinary->getUniformByLocation(location); @@ -995,7 +1068,8 @@ static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniform // attempting to write an array to a non-array uniform is an INVALID_OPERATION if (uniform->elementCount() == 1 && count > 1) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } *uniformOut = uniform; @@ -1007,7 +1081,8 @@ bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, G // Check for ES3 uniform entry points if (VariableComponentType(uniformType) == GL_UNSIGNED_INT && context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } LinkedUniform *uniform = NULL; @@ -1020,7 +1095,8 @@ bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, G bool samplerUniformCheck = (IsSampler(uniform->type) && uniformType == GL_INT); if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } return true; @@ -1034,12 +1110,14 @@ bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint locati int cols = VariableColumnCount(matrixType); if (rows != cols && context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (transpose != GL_FALSE && context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } LinkedUniform *uniform = NULL; @@ -1050,7 +1128,8 @@ bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint locati if (uniform->type != matrixType) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } return true; @@ -1060,7 +1139,8 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, { if (!context->getQueryParameterInfo(pname, nativeType, numParams)) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15) @@ -1069,7 +1149,8 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, if (colorAttachment >= context->getCaps().maxDrawBuffers) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -1079,9 +1160,10 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, case GL_TEXTURE_BINDING_CUBE_MAP: case GL_TEXTURE_BINDING_3D: case GL_TEXTURE_BINDING_2D_ARRAY: - if (context->getState().getActiveSampler() >= context->getMaximumCombinedTextureImageUnits()) + if (context->getState().getActiveSampler() >= context->getCaps().maxCombinedTextureImageUnits) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; @@ -1092,13 +1174,15 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, ASSERT(framebuffer); if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); if (!attachment) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } break; @@ -1123,46 +1207,51 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi if (!ValidTexture2DDestinationTarget(context, target)) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (std::numeric_limits::max() - xoffset < width || std::numeric_limits::max() - yoffset < height) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (border != 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (!ValidMipLevel(context, target, level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; } if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } const gl::Caps &caps = context->getCaps(); gl::Texture *texture = NULL; GLenum textureInternalFormat = GL_NONE; - bool textureCompressed = false; - bool textureIsDepth = false; GLint textureLevelWidth = 0; GLint textureLevelHeight = 0; GLint textureLevelDepth = 0; @@ -1176,8 +1265,6 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi if (texture2d) { textureInternalFormat = texture2d->getInternalFormat(level); - textureCompressed = texture2d->isCompressed(level); - textureIsDepth = texture2d->isDepth(level); textureLevelWidth = texture2d->getWidth(level); textureLevelHeight = texture2d->getHeight(level); textureLevelDepth = 1; @@ -1198,8 +1285,6 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi if (textureCube) { textureInternalFormat = textureCube->getInternalFormat(target, level); - textureCompressed = textureCube->isCompressed(target, level); - textureIsDepth = false; textureLevelWidth = textureCube->getWidth(target, level); textureLevelHeight = textureCube->getHeight(target, level); textureLevelDepth = 1; @@ -1215,8 +1300,6 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi if (texture2dArray) { textureInternalFormat = texture2dArray->getInternalFormat(level); - textureCompressed = texture2dArray->isCompressed(level); - textureIsDepth = texture2dArray->isDepth(level); textureLevelWidth = texture2dArray->getWidth(level); textureLevelHeight = texture2dArray->getHeight(level); textureLevelDepth = texture2dArray->getLayers(level); @@ -1232,8 +1315,6 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi if (texture3d) { textureInternalFormat = texture3d->getInternalFormat(level); - textureCompressed = texture3d->isCompressed(level); - textureIsDepth = texture3d->isDepth(level); textureLevelWidth = texture3d->getWidth(level); textureLevelHeight = texture3d->getHeight(level); textureLevelDepth = texture3d->getDepth(level); @@ -1244,33 +1325,37 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (!texture) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (texture->isImmutable() && !isSubImage) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (textureIsDepth) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + + if (formatInfo.depthBits > 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (textureCompressed) + if (formatInfo.compressed) { - GLint blockWidth = GetCompressedBlockWidth(textureInternalFormat); - GLint blockHeight = GetCompressedBlockHeight(textureInternalFormat); - - if (((width % blockWidth) != 0 && width != textureLevelWidth) || - ((height % blockHeight) != 0 && height != textureLevelHeight)) + if (((width % formatInfo.compressedBlockWidth) != 0 && width != textureLevelWidth) || + ((height % formatInfo.compressedBlockHeight) != 0 && height != textureLevelHeight)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -1280,25 +1365,29 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi yoffset + height > textureLevelHeight || zoffset >= textureLevelDepth) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } else { if (IsCubemapTextureTarget(target) && width != height) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } - if (!IsValidInternalFormat(internalformat, context->getExtensions(), context->getClientVersion())) + if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } int maxLevelDimension = (maxDimension >> level); if (static_cast(width) > maxLevelDimension || static_cast(height) > maxLevelDimension) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } @@ -1306,7 +1395,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi return true; } -static bool ValidateDrawBase(const gl::Context *context, GLenum mode, GLsizei count) +static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsizei maxVertex, GLsizei primcount) { switch (mode) { @@ -1319,71 +1408,128 @@ static bool ValidateDrawBase(const gl::Context *context, GLenum mode, GLsizei co case GL_TRIANGLE_FAN: break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (count < 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } + const State &state = context->getState(); + // Check for mapped buffers - if (context->hasMappedBuffer(GL_ARRAY_BUFFER)) + if (state.hasMappedBuffer(GL_ARRAY_BUFFER)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - const gl::DepthStencilState &depthStencilState = context->getState().getDepthStencilState(); + const gl::DepthStencilState &depthStencilState = state.getDepthStencilState(); if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || - context->getState().getStencilRef() != context->getState().getStencilBackRef() || + 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."); - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer(); + const gl::Framebuffer *fbo = state.getDrawFramebuffer(); if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; + } + + if (state.getCurrentProgramId() == 0) + { + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (context->getState().getCurrentProgramId() == 0) + gl::ProgramBinary *programBinary = state.getCurrentProgramBinary(); + if (!programBinary->validateSamplers(NULL, context->getCaps())) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); - if (!programBinary->validateSamplers(NULL)) + // Buffer validations + const VertexArray *vao = state.getVertexArray(); + for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) { - return gl::error(GL_INVALID_OPERATION, false); + 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(const gl::Context *context, GLenum mode, GLint first, GLsizei count) +bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount) { if (first < 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } - gl::TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback(); + 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) - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (!ValidateDrawBase(context, mode, count)) + if (!ValidateDrawBase(context, mode, count, count, primcount)) { return false; } @@ -1391,14 +1537,15 @@ bool ValidateDrawArrays(const gl::Context *context, GLenum mode, GLint first, GL return true; } -bool ValidateDrawArraysInstanced(const gl::Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount) +bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount) { if (primcount < 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } - if (!ValidateDrawArrays(context, mode, first, count)) + if (!ValidateDrawArrays(context, mode, first, count, primcount)) { return false; } @@ -1407,7 +1554,41 @@ bool ValidateDrawArraysInstanced(const gl::Context *context, GLenum mode, GLint return (primcount > 0); } -bool ValidateDrawElements(const gl::Context *context, GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) +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) { @@ -1417,34 +1598,89 @@ bool ValidateDrawElements(const gl::Context *context, GLenum mode, GLsizei count case GL_UNSIGNED_INT: if (!context->getExtensions().elementIndexUint) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } - gl::TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback(); + 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) - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } // Check for mapped buffers - if (context->hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER)) + 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) { - return gl::error(GL_INVALID_OPERATION, false); + 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; } - gl::VertexArray *vao = context->getState().getVertexArray(); - if (!indices && !vao->getElementArrayBuffer()) + // 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) + { + GLint64 offset = reinterpret_cast(indices); + if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut, NULL)) + { + const void *dataPointer = elementArrayBuffer->getImplementation()->getData(); + const uint8_t *offsetPointer = static_cast(dataPointer) + offset; + *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, offsetPointer, count); + } + } + else { - return gl::error(GL_INVALID_OPERATION, false); + *indexRangeOut = rx::IndexRangeCache::ComputeRange(type, indices, count); } - if (!ValidateDrawBase(context, mode, count)) + if (!ValidateDrawBase(context, mode, count, static_cast(indexRangeOut->end), primcount)) { return false; } @@ -1452,15 +1688,18 @@ bool ValidateDrawElements(const gl::Context *context, GLenum mode, GLsizei count return true; } -bool ValidateDrawElementsInstanced(const gl::Context *context, GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei primcount) +bool ValidateDrawElementsInstanced(Context *context, + GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei primcount, + rx::RangeUI *indexRangeOut) { if (primcount < 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } - if (!ValidateDrawElements(context, mode, count, type, indices)) + if (!ValidateDrawElements(context, mode, count, type, indices, primcount, indexRangeOut)) { return false; } @@ -1469,12 +1708,24 @@ bool ValidateDrawElementsInstanced(const gl::Context *context, GLenum mode, GLsi return (primcount > 0); } -bool ValidateFramebufferTextureBase(const gl::Context *context, GLenum target, GLenum attachment, +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)) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (!ValidateAttachmentTarget(context, attachment)) @@ -1488,12 +1739,14 @@ bool ValidateFramebufferTextureBase(const gl::Context *context, GLenum target, G if (tex == NULL) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (level < 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } @@ -1502,19 +1755,21 @@ bool ValidateFramebufferTextureBase(const gl::Context *context, GLenum target, G if (framebufferHandle == 0 || !framebuffer) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } return true; } -bool ValidateFramebufferTexture2D(const gl::Context *context, GLenum target, GLenum attachment, +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) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level)) @@ -1535,16 +1790,19 @@ bool ValidateFramebufferTexture2D(const gl::Context *context, GLenum target, GLe { if (level > gl::log2(caps.max2DTextureSize)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (tex->getTarget() != GL_TEXTURE_2D) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } gl::Texture2D *tex2d = static_cast(tex); if (tex2d->isCompressed(level)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } break; @@ -1558,26 +1816,105 @@ bool ValidateFramebufferTexture2D(const gl::Context *context, GLenum target, GLe { if (level > gl::log2(caps.maxCubeMapTextureSize)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (tex->getTarget() != GL_TEXTURE_CUBE_MAP) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } gl::TextureCubeMap *texcube = static_cast(tex); if (texcube->isCompressed(textarget, level)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } break; default: - return gl::error(GL_INVALID_ENUM, false); + 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; + } + + 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 index 849df36588..1fdb633cb6 100644 --- a/src/3rdparty/angle/src/libGLESv2/validationES.h +++ b/src/3rdparty/angle/src/libGLESv2/validationES.h @@ -9,6 +9,11 @@ #ifndef LIBGLESV2_VALIDATION_ES_H #define LIBGLESV2_VALIDATION_ES_H +#include "common/mathutil.h" + +#include +#include + namespace gl { @@ -21,55 +26,67 @@ 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 gl::Context *context, GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth); -bool ValidCompressedImageSize(const gl::Context *context, GLenum internalFormat, GLsizei width, GLsizei height); -bool ValidQueryType(const gl::Context *context, GLenum queryType); -bool ValidProgram(const gl::Context *context, GLuint id); +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(const gl::Context *context, GLenum attachment); -bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum target, GLsizei samples, +bool ValidateAttachmentTarget(Context *context, GLenum attachment); +bool ValidateRenderbufferStorageParameters(Context *context, GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, bool angleExtension); -bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment, +bool ValidateFramebufferRenderbufferParameters(Context *context, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); -bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, +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(GLenum pname, int clientVersion); +bool ValidateGetVertexAttribParameters(Context *context, GLenum pname); -bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param); +bool ValidateTexParamParameters(Context *context, GLenum pname, GLint param); -bool ValidateSamplerObjectParameter(GLenum pname); +bool ValidateSamplerObjectParameter(Context *context, GLenum pname); -bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsizei width, GLsizei height, +bool ValidateReadPixelsParameters(Context *context, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels); -bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id); -bool ValidateEndQuery(gl::Context *context, GLenum target); +bool ValidateBeginQuery(Context *context, GLenum target, GLuint id); +bool ValidateEndQuery(Context *context, GLenum target); -bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count); -bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count, +bool ValidateUniform(Context *context, GLenum uniformType, GLint location, GLsizei count); +bool ValidateUniformMatrix(Context *context, GLenum matrixType, GLint location, GLsizei count, GLboolean transpose); -bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams); +bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams); -bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, +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(const gl::Context *context, GLenum mode, GLint first, GLsizei count); -bool ValidateDrawArraysInstanced(const gl::Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount); -bool ValidateDrawElements(const gl::Context *context, GLenum mode, GLsizei count, GLenum type, const GLvoid* indices); -bool ValidateDrawElementsInstanced(const gl::Context *context, GLenum mode, GLsizei count, GLenum type, - const GLvoid *indices, GLsizei primcount); +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 ValidateFramebufferTextureBase(const gl::Context *context, GLenum target, GLenum attachment, +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(const gl::Context *context, GLenum target, GLenum attachment, +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 index 1a09400322..f950454df0 100644 --- a/src/3rdparty/angle/src/libGLESv2/validationES2.cpp +++ b/src/3rdparty/angle/src/libGLESv2/validationES2.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -23,26 +22,28 @@ namespace gl { -static bool validateSubImageParams2D(bool compressed, GLsizei width, GLsizei height, +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) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (compressed != texture->isCompressed(level)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (format != GL_NONE) { - GLenum internalformat = gl::GetSizedInternalFormat(format, type); - if (internalformat != texture->getInternalFormat(level)) + if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(level)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -51,39 +52,43 @@ static bool validateSubImageParams2D(bool compressed, GLsizei width, GLsizei hei if ((width % 4 != 0 && width != texture->getWidth(level)) || (height % 4 != 0 && height != texture->getHeight(level))) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } if (xoffset + width > texture->getWidth(level) || yoffset + height > texture->getHeight(level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } return true; } -static bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height, +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) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (compressed != texture->isCompressed(target, level)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (format != GL_NONE) { - GLenum internalformat = gl::GetSizedInternalFormat(format, type); - if (internalformat != texture->getInternalFormat(target, level)) + if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, level)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -92,43 +97,49 @@ static bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei h if ((width % 4 != 0 && width != texture->getWidth(target, 0)) || (height % 4 != 0 && height != texture->getHeight(target, 0))) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } if (xoffset + width > texture->getWidth(target, level) || yoffset + height > texture->getHeight(target, level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } return true; } -bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, +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)) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (!ValidImageSize(context, target, level, width, height, 1)) { - return gl::error(GL_INVALID_VALUE, false); + 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) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (!isSubImage && !isCompressed && internalformat != format) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } const gl::Caps &caps = context->getCaps(); @@ -145,7 +156,8 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le if (static_cast(width) > (caps.max2DTextureSize >> level) || static_cast(height) > (caps.max2DTextureSize >> level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } gl::Texture2D *tex2d = context->getTexture2D(); @@ -158,7 +170,7 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le texture = tex2d; } - if (isSubImage && !validateSubImageParams2D(isCompressed, width, height, xoffset, yoffset, + if (isSubImage && !ValidateSubImageParams2D(context, isCompressed, width, height, xoffset, yoffset, level, format, type, tex2d)) { return false; @@ -177,13 +189,15 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le { if (!isSubImage && width != height) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (static_cast(width) > (caps.maxCubeMapTextureSize >> level) || static_cast(height) > (caps.maxCubeMapTextureSize >> level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } gl::TextureCubeMap *texCube = context->getTextureCubeMap(); @@ -196,7 +210,7 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le texture = texCube; } - if (isSubImage && !validateSubImageParamsCube(isCompressed, width, height, xoffset, yoffset, + if (isSubImage && !ValidateSubImageParamsCube(context, isCompressed, width, height, xoffset, yoffset, target, level, format, type, texCube)) { return false; @@ -205,23 +219,27 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (!texture) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (!isSubImage && texture->isImmutable()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } // Verify zero border if (border != 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat; @@ -229,7 +247,8 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le { if (!ValidCompressedImageSize(context, actualInternalFormat, width, height)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } switch (actualInternalFormat) @@ -238,23 +257,27 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: if (!context->getExtensions().textureCompressionDXT1) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: if (!context->getExtensions().textureCompressionDXT1) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (!context->getExtensions().textureCompressionDXT5) + if (!context->getExtensions().textureCompressionDXT5) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } else @@ -273,7 +296,8 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_FLOAT: break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } // validate + combinations @@ -290,15 +314,17 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_FLOAT: case GL_HALF_FLOAT_OES: break; - default: - return gl::error(GL_INVALID_OPERATION, false); + default: + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RED: case GL_RG: if (!context->getExtensions().textureRG) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } switch (type) { @@ -307,7 +333,8 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_HALF_FLOAT_OES: break; default: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RGB: @@ -319,7 +346,8 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_HALF_FLOAT_OES: break; default: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RGBA: @@ -332,7 +360,8 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_HALF_FLOAT_OES: break; default: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_BGRA_EXT: @@ -341,21 +370,24 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_UNSIGNED_BYTE: break; default: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_SRGB_EXT: case GL_SRGB_ALPHA_EXT: if (!context->getExtensions().sRGB) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } switch (type) { case GL_UNSIGNED_BYTE: break; default: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below @@ -370,7 +402,8 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_UNSIGNED_INT: break; default: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_DEPTH_STENCIL_OES: @@ -379,11 +412,13 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_UNSIGNED_INT_24_8_OES: break; default: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } switch (format) @@ -392,48 +427,57 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: if (context->getExtensions().textureCompressionDXT1) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } else { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: if (context->getExtensions().textureCompressionDXT3) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } else { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: if (context->getExtensions().textureCompressionDXT5) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } else { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL_OES: if (!context->getExtensions().depthTextures) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (target != GL_TEXTURE_2D) { - return gl::error(GL_INVALID_OPERATION, false); + 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) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; default: @@ -444,14 +488,16 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le { if (!context->getExtensions().textureFloat) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } else if (type == GL_HALF_FLOAT_OES) { if (!context->getExtensions().textureHalfFloat) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } } @@ -461,7 +507,7 @@ bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint le -bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, +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) { @@ -475,7 +521,7 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat(); - GLenum textureFormat = gl::GetFormat(textureInternalFormat); + GLenum textureFormat = gl::GetInternalFormatInfo(textureInternalFormat).format; // [OpenGL ES 2.0.24] table 3.9 if (isSubImage) @@ -488,7 +534,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_LUMINANCE: @@ -500,7 +547,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RED_EXT: @@ -512,7 +560,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RG_EXT: @@ -523,7 +572,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RGB: @@ -533,7 +583,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_LUMINANCE_ALPHA: @@ -542,19 +593,23 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_RGB5_A1 && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + 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: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; case GL_DEPTH_COMPONENT: case GL_DEPTH_STENCIL_OES: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; default: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } else @@ -568,7 +623,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_LUMINANCE: @@ -581,7 +637,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RED_EXT: @@ -594,7 +651,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RG_EXT: @@ -606,7 +664,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_RGB: @@ -617,7 +676,8 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; case GL_LUMINANCE_ALPHA: @@ -627,38 +687,45 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin colorbufferFormat != GL_BGRA8_EXT && colorbufferFormat != GL_RGBA8_OES) { - return gl::error(GL_INVALID_OPERATION, false); + 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) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } else { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: if (context->getExtensions().textureCompressionDXT3) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } else { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: if (context->getExtensions().textureCompressionDXT5) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } else { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_DEPTH_COMPONENT: @@ -668,14 +735,17 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin case GL_DEPTH24_STENCIL8_OES: if (context->getExtensions().depthTextures) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } else { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } @@ -683,35 +753,38 @@ bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLin return (width > 0 && height > 0); } -bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat, +bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (width < 1 || height < 1 || levels < 1) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (target == GL_TEXTURE_CUBE_MAP && width != height) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - GLenum format = gl::GetFormat(internalformat); - GLenum type = gl::GetType(internalformat); - - if (format == GL_NONE || type == GL_NONE) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + if (formatInfo.format == GL_NONE || formatInfo.type == GL_NONE) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } const gl::Caps &caps = context->getCaps(); @@ -722,25 +795,29 @@ bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsize if (static_cast(width) > caps.max2DTextureSize || static_cast(height) > caps.max2DTextureSize) { - return gl::error(GL_INVALID_VALUE, false); + 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) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (levels != 1 && !context->getExtensions().textureNPOT) { if (!gl::isPow2(width) || !gl::isPow2(height)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -750,19 +827,22 @@ bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsize case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: if (!context->getExtensions().textureCompressionDXT1) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: if (!context->getExtensions().textureCompressionDXT3) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: if (!context->getExtensions().textureCompressionDXT5) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_RGBA32F_EXT: @@ -772,7 +852,8 @@ bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsize case GL_LUMINANCE_ALPHA32F_EXT: if (!context->getExtensions().textureFloat) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_RGBA16F_EXT: @@ -782,7 +863,8 @@ bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsize case GL_LUMINANCE_ALPHA16F_EXT: if (!context->getExtensions().textureHalfFloat) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_R8_EXT: @@ -793,7 +875,8 @@ bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsize case GL_RG32F_EXT: if (!context->getExtensions().textureRG) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_DEPTH_COMPONENT16: @@ -801,16 +884,19 @@ bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsize case GL_DEPTH24_STENCIL8_OES: if (!context->getExtensions().depthTextures) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (target != GL_TEXTURE_2D) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } // ANGLE_depth_texture only supports 1-level textures if (levels != 1) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } break; default: @@ -832,19 +918,21 @@ bool ValidateES2TexStorageParameters(gl::Context *context, GLenum target, GLsize if (!texture || texture->id() == 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (texture->isImmutable()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } return true; } // check for combinations of format and type that are valid for ReadPixels -bool ValidES2ReadFormatType(gl::Context *context, GLenum format, GLenum type) +bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type) { switch (format) { diff --git a/src/3rdparty/angle/src/libGLESv2/validationES2.h b/src/3rdparty/angle/src/libGLESv2/validationES2.h index e41e345876..53a0b630ea 100644 --- a/src/3rdparty/angle/src/libGLESv2/validationES2.h +++ b/src/3rdparty/angle/src/libGLESv2/validationES2.h @@ -9,23 +9,25 @@ #ifndef LIBGLESV2_VALIDATION_ES2_H #define LIBGLESV2_VALIDATION_ES2_H +#include + namespace gl { class Context; -bool ValidateES2TexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, +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(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, +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(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat, +bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); -bool ValidES2ReadFormatType(gl::Context *context, GLenum format, GLenum type); +bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type); } diff --git a/src/3rdparty/angle/src/libGLESv2/validationES3.cpp b/src/3rdparty/angle/src/libGLESv2/validationES3.cpp index a584a7127b..251c6ad2c4 100644 --- a/src/3rdparty/angle/src/libGLESv2/validationES3.cpp +++ b/src/3rdparty/angle/src/libGLESv2/validationES3.cpp @@ -1,4 +1,3 @@ -#include "precompiled.h" // // 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 @@ -22,25 +21,283 @@ namespace gl { -bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, +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)) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } // Validate image size if (!ValidImageSize(context, target, level, width, height, depth)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } // Verify zero border if (border != 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (xoffset < 0 || yoffset < 0 || zoffset < 0 || @@ -48,7 +305,8 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le std::numeric_limits::max() - yoffset < height || std::numeric_limits::max() - zoffset < depth) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } const gl::Caps &caps = context->getCaps(); @@ -66,7 +324,8 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le if (static_cast(width) > (caps.max2DTextureSize >> level) || static_cast(height) > (caps.max2DTextureSize >> level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } gl::Texture2D *texture2d = context->getTexture2D(); @@ -91,12 +350,14 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le { if (!isSubImage && width != height) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (static_cast(width) > (caps.maxCubeMapTextureSize >> level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); @@ -118,7 +379,8 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le static_cast(height) > (caps.max3DTextureSize >> level) || static_cast(depth) > (caps.max3DTextureSize >> level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } gl::Texture3D *texture3d = context->getTexture3D(); @@ -140,7 +402,8 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le static_cast(height) > (caps.max2DTextureSize >> level) || static_cast(depth) > (caps.maxArrayTextureLayers >> level)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } gl::Texture2DArray *texture2darray = context->getTexture2DArray(); @@ -157,57 +420,56 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (!texture) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (texture->isImmutable() && !isSubImage) { - return gl::error(GL_INVALID_OPERATION, false); + 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)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (!gl::IsFormatCompressed(actualInternalFormat)) + if (!actualFormatInfo.compressed) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (target == GL_TEXTURE_3D) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } else { - // Note: dEQP 2013.4 expects an INVALID_VALUE error for TexImage3D with an invalid - // internal format. (dEQP-GLES3.functional.negative_api.texture.teximage3d) - if (!gl::IsValidInternalFormat(actualInternalFormat, context->getExtensions(), context->getClientVersion()) || - !gl::IsValidFormat(format, context->getExtensions(), context->getClientVersion()) || - !gl::IsValidType(type, context->getExtensions(), context->getClientVersion())) - { - return gl::error(GL_INVALID_ENUM, false); - } - - if (!gl::IsValidFormatCombination(actualInternalFormat, format, type, context->getExtensions(), context->getClientVersion())) + if (!ValidateTexImageFormatCombination(context, actualInternalFormat, format, type)) { - return gl::error(GL_INVALID_OPERATION, false); + return false; } if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -216,7 +478,8 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le { if (isCompressed != textureCompressed) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (isCompressed) @@ -224,7 +487,8 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le if ((width % 4 != 0 && width != textureLevelWidth) || (height % 4 != 0 && height != textureLevelHeight)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -235,21 +499,24 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le if (xoffset < 0 || yoffset < 0 || zoffset < 0) { - return gl::error(GL_INVALID_VALUE, false); + 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) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (xoffset + width > textureLevelWidth || yoffset + height > textureLevelHeight || zoffset + depth > textureLevelDepth) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } @@ -262,17 +529,17 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le size_t widthSize = static_cast(width); size_t heightSize = static_cast(height); size_t depthSize = static_cast(depth); - GLenum sizedFormat = gl::IsSizedInternalFormat(actualInternalFormat) ? actualInternalFormat - : gl::GetSizedInternalFormat(actualInternalFormat, type); + GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type); - size_t pixelBytes = static_cast(gl::GetPixelBytes(sizedFormat)); + 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 - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } size_t copyBytes = widthSize * heightSize * depthSize * pixelBytes; @@ -282,29 +549,316 @@ bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint le ((offset + copyBytes) > static_cast(pixelUnpackBuffer->getSize()))) { // Overflow past the end of the buffer - return gl::error(GL_INVALID_OPERATION, false); + 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. - size_t dataBytesPerPixel = static_cast(gl::GetTypeBytes(type)); + size_t dataBytesPerPixel = static_cast(gl::GetTypeInfo(type).bytes); if ((offset % dataBytesPerPixel) != 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } // ...the buffer object's data store is currently mapped. if (pixelUnpackBuffer->isMapped()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } return true; } -bool ValidateES3CopyTexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat, +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) { @@ -320,12 +874,14 @@ bool ValidateES3CopyTexImageParameters(gl::Context *context, GLenum target, GLin if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION)); + return false; } if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer(); @@ -333,20 +889,20 @@ bool ValidateES3CopyTexImageParameters(gl::Context *context, GLenum target, GLin if (isSubImage) { - if (!gl::IsValidCopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat, - context->getState().getReadFramebuffer()->id(), - context->getClientVersion())) + if (!IsValidES3CopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat, + context->getState().getReadFramebuffer()->id())) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } else { - if (!gl::IsValidCopyTexImageCombination(internalformat, colorbufferInternalFormat, - context->getState().getReadFramebuffer()->id(), - context->getClientVersion())) + if (!gl::IsValidES3CopyTexImageCombination(internalformat, colorbufferInternalFormat, + context->getState().getReadFramebuffer()->id())) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } @@ -354,17 +910,19 @@ bool ValidateES3CopyTexImageParameters(gl::Context *context, GLenum target, GLin return (width > 0 && height > 0); } -bool ValidateES3TexStorageParameters(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat, +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) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } const gl::Caps &caps = context->getCaps(); @@ -379,7 +937,8 @@ bool ValidateES3TexStorageParameters(gl::Context *context, GLenum target, GLsize if (static_cast(width) > caps.max2DTextureSize || static_cast(height) > caps.max2DTextureSize) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } break; @@ -390,12 +949,14 @@ bool ValidateES3TexStorageParameters(gl::Context *context, GLenum target, GLsize if (width != height) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (static_cast(width) > caps.maxCubeMapTextureSize) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } break; @@ -408,7 +969,8 @@ bool ValidateES3TexStorageParameters(gl::Context *context, GLenum target, GLsize static_cast(height) > caps.max3DTextureSize || static_cast(depth) > caps.max3DTextureSize) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } break; @@ -421,49 +983,58 @@ bool ValidateES3TexStorageParameters(gl::Context *context, GLenum target, GLsize static_cast(height) > caps.max2DTextureSize || static_cast(depth) > caps.maxArrayTextureLayers) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } } break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (!texture || texture->id() == 0) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (texture->isImmutable()) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } - if (!gl::IsValidInternalFormat(internalformat, context->getExtensions(), context->getClientVersion())) + const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat); + if (!formatInfo.textureSupport(context->getClientVersion(), context->getExtensions())) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } - if (!gl::IsSizedInternalFormat(internalformat)) + if (formatInfo.pixelBytes == 0) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } return true; } -bool ValidateFramebufferTextureLayer(const gl::Context *context, GLenum target, GLenum attachment, +bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } if (layer < 0) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level)) @@ -483,18 +1054,21 @@ bool ValidateFramebufferTextureLayer(const gl::Context *context, GLenum target, { if (level > gl::log2(caps.max2DTextureSize)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (static_cast(layer) >= caps.maxArrayTextureLayers) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } gl::Texture2DArray *texArray = static_cast(tex); if (texArray->isCompressed(level)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } break; @@ -503,32 +1077,38 @@ bool ValidateFramebufferTextureLayer(const gl::Context *context, GLenum target, { if (level > gl::log2(caps.max3DTextureSize)) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } if (static_cast(layer) >= caps.max3DTextureSize) { - return gl::error(GL_INVALID_VALUE, false); + context->recordError(Error(GL_INVALID_VALUE)); + return false; } gl::Texture3D *tex3d = static_cast(tex); if (tex3d->isCompressed(level)) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } break; default: - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } return true; } -bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type) +bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type) { + const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat); + switch (format) { case GL_RGBA: @@ -543,7 +1123,7 @@ bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum } break; case GL_FLOAT: - if (gl::GetComponentType(internalFormat) != GL_FLOAT) + if (internalFormatInfo.componentType != GL_FLOAT) { return false; } @@ -556,13 +1136,13 @@ bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum switch (type) { case GL_INT: - if (gl::GetComponentType(internalFormat) != GL_INT) + if (internalFormatInfo.componentType != GL_INT) { return false; } break; case GL_UNSIGNED_INT: - if (gl::GetComponentType(internalFormat) != GL_UNSIGNED_INT) + if (internalFormatInfo.componentType != GL_UNSIGNED_INT) { return false; } @@ -602,7 +1182,7 @@ bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum return true; } -bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target, GLsizei numAttachments, +bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments, const GLenum* attachments) { bool defaultFramebuffer = false; @@ -617,7 +1197,8 @@ bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0; break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } for (int i = 0; i < numAttachments; ++i) @@ -626,12 +1207,14 @@ bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target { if (defaultFramebuffer) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } } else @@ -643,7 +1226,8 @@ bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target case GL_DEPTH_STENCIL_ATTACHMENT: if (defaultFramebuffer) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; case GL_COLOR: @@ -651,11 +1235,13 @@ bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target case GL_STENCIL: if (!defaultFramebuffer) { - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } break; default: - return gl::error(GL_INVALID_ENUM, false); + context->recordError(Error(GL_INVALID_ENUM)); + return false; } } } @@ -663,20 +1249,33 @@ bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target return true; } -bool ValidateClearBuffer(const gl::Context *context) +bool ValidateClearBuffer(Context *context) { if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION, false); + context->recordError(Error(GL_INVALID_OPERATION)); + return false; } const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer(); if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE) { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + 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 index 4d068bd094..cafacca601 100644 --- a/src/3rdparty/angle/src/libGLESv2/validationES3.h +++ b/src/3rdparty/angle/src/libGLESv2/validationES3.h @@ -9,31 +9,35 @@ #ifndef LIBGLESV2_VALIDATION_ES3_H #define LIBGLESV2_VALIDATION_ES3_H +#include + namespace gl { class Context; -bool ValidateES3TexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage, +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(gl::Context *context, GLenum target, GLint level, GLenum internalformat, +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(gl::Context *context, GLenum target, GLsizei levels, GLenum internalformat, +bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); -bool ValidateFramebufferTextureLayer(const gl::Context *context, GLenum target, GLenum attachment, +bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); -bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type); +bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type); -bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target, GLsizei numAttachments, +bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments, const GLenum* attachments); -bool ValidateClearBuffer(const gl::Context *context); +bool ValidateClearBuffer(Context *context); + +bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params); } diff --git a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h index 7d06a6c70d..30bb7e3b94 100644 --- a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h +++ b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h @@ -27,7 +27,7 @@ #define THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_ #include "compiler/translator/InfoSink.h" -#include "compiler/translator/intermediate.h" +#include "compiler/translator/IntermNode.h" class ArrayBoundsClamper { public: diff --git a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h deleted file mode 100644 index 96ac910b08..0000000000 --- a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h +++ /dev/null @@ -1,828 +0,0 @@ -// 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(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; -}; - -// TraceEventSamplingStateScope records the current sampling state -// and sets a new sampling state. When the scope exists, it restores -// the sampling state having recorded. -#if 0 // This is not used by ANGLE and causes a compilation error on MinGW -template -class SamplingStateScope { -public: - SamplingStateScope(const char* categoryAndName) - { - m_previousState = SamplingStateScope::current(); - SamplingStateScope::set(categoryAndName); - } - - ~SamplingStateScope() - { - SamplingStateScope::set(m_previousState); - } - - // FIXME: Make load/store to traceSamplingState[] thread-safe and atomic. - static inline const char* current() - { - return reinterpret_cast(*gl::traceSamplingState[BucketNumber]); - } - static inline void set(const char* categoryAndName) - { - *gl::traceSamplingState[BucketNumber] = reinterpret_cast(const_cast(categoryAndName)); - } - -private: - const char* m_previousState; -}; -#endif - -} // namespace TraceEvent - -} // namespace gl - -#endif -- cgit v1.2.3