From a6a12d8c0fc918972c15268f749ecc7c90b95d6c Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Tue, 5 Aug 2014 12:59:44 +0300 Subject: ANGLE: upgrade to 2.1~07d49ef5350a This version of ANGLE provides partial ES3 support, numerous bug fixes, and several potentially useful vendor extensions. All patches have been rebased. The following changes are noted: 0000-General-fixes-for-ANGLE-2.1.patch contains compile fixes for the new ANGLE 0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch has incorporated patch 0015. 0007-Make-DX9-DX11-mutually-exclusive.patch has been removed as it was fixed upstream. 0007-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch has been moved up to fill the patch number gap. 0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch now contains patch 0014 and 0017. 0013-ANGLE-Allow-for-universal-program-binaries.patch has been removed as it is no longer relevant. 0014-ANGLE-D3D11-Fix-internal-index-buffer-for-level-9-ha.patch has been merged with patch 0010. 0015-ANGLE-Don-t-export-DLLMain-functions-for-static-buil.patch has been merged with patch 0004. 0016-ANGLE-WinRT-Call-Trim-when-application-suspends.patch has been removed and will be replaced by a follow-up patch using a different technique. 0017-ANGLE-D3D11-Don-t-use-mipmaps-in-level-9-textures.patch has been merged with patch 0010. 0018-ANGLE-WinRT-Create-swap-chain-using-physical-resolut.patch has been removed and will be replaced by a follow-up patch extending the EGL_ANGLE_window_fixed_size extension. 0019-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch is now patch 0007. [ChangeLog][Third-party libraries] ANGLE has been upgraded to version 2.1, bringing partial support for OpenGL ES3 over Direct3D 11, numerous bug fixes, and several new vendor extensions. Change-Id: I6d95ce1480462d67228d83c1e5c74a1706b5b21c Reviewed-by: Friedemann Kleint --- src/3rdparty/angle/.gitignore | 25 +- src/3rdparty/angle/CONTRIBUTORS | 3 + src/3rdparty/angle/include/EGL/egl.h | 557 +- src/3rdparty/angle/include/EGL/eglext.h | 880 +- src/3rdparty/angle/include/EGL/eglplatform.h | 30 +- src/3rdparty/angle/include/GLES2/gl2.h | 9 +- src/3rdparty/angle/include/GLES2/gl2ext.h | 593 +- src/3rdparty/angle/include/GLES3/gl3.h | 1061 ++ src/3rdparty/angle/include/GLES3/gl3ext.h | 24 + src/3rdparty/angle/include/GLES3/gl3platform.h | 30 + src/3rdparty/angle/include/GLSLANG/ShaderLang.h | 146 +- src/3rdparty/angle/include/angle_gl.h | 26 + src/3rdparty/angle/src/commit.h | 12 +- src/3rdparty/angle/src/common/RefCountObject.h | 38 +- src/3rdparty/angle/src/common/angleutils.h | 79 +- src/3rdparty/angle/src/common/blocklayout.cpp | 289 + src/3rdparty/angle/src/common/blocklayout.h | 128 + src/3rdparty/angle/src/common/debug.cpp | 53 +- src/3rdparty/angle/src/common/debug.h | 32 +- src/3rdparty/angle/src/common/event_tracer.cpp | 2 +- src/3rdparty/angle/src/common/event_tracer.h | 12 +- src/3rdparty/angle/src/common/mathutil.cpp | 66 + src/3rdparty/angle/src/common/mathutil.h | 545 + src/3rdparty/angle/src/common/platform.h | 73 + src/3rdparty/angle/src/common/shadervars.h | 157 + src/3rdparty/angle/src/common/tls.cpp | 103 + src/3rdparty/angle/src/common/tls.h | 37 + src/3rdparty/angle/src/common/utilities.cpp | 527 + src/3rdparty/angle/src/common/utilities.h | 52 + src/3rdparty/angle/src/common/version.h | 6 +- .../src/compiler/preprocessor/DiagnosticsBase.cpp | 80 +- .../src/compiler/preprocessor/DiagnosticsBase.h | 6 +- .../compiler/preprocessor/DirectiveHandlerBase.h | 18 +- .../src/compiler/preprocessor/DirectiveParser.cpp | 171 +- .../src/compiler/preprocessor/DirectiveParser.h | 62 +- .../src/compiler/preprocessor/ExpressionParser.h | 8 +- .../src/compiler/preprocessor/ExpressionParser.y | 85 +- .../angle/src/compiler/preprocessor/Input.cpp | 4 +- .../angle/src/compiler/preprocessor/Input.h | 29 +- .../angle/src/compiler/preprocessor/Lexer.h | 2 +- .../angle/src/compiler/preprocessor/Macro.cpp | 2 +- .../angle/src/compiler/preprocessor/Macro.h | 9 +- .../src/compiler/preprocessor/MacroExpander.cpp | 64 +- .../src/compiler/preprocessor/MacroExpander.h | 60 +- .../src/compiler/preprocessor/Preprocessor.cpp | 35 +- .../angle/src/compiler/preprocessor/Preprocessor.h | 19 +- .../src/compiler/preprocessor/SourceLocation.h | 18 +- .../angle/src/compiler/preprocessor/Token.cpp | 10 +- .../angle/src/compiler/preprocessor/Token.h | 35 +- .../angle/src/compiler/preprocessor/Tokenizer.h | 16 +- .../angle/src/compiler/preprocessor/Tokenizer.l | 34 +- .../src/compiler/preprocessor/length_limits.h | 21 - .../angle/src/compiler/preprocessor/numeric_lex.h | 8 +- .../angle/src/compiler/preprocessor/pp_utils.h | 4 +- .../angle/src/compiler/translator/BaseTypes.h | 352 +- .../translator/BuiltInFunctionEmulator.cpp | 16 +- .../compiler/translator/BuiltInFunctionEmulator.h | 4 +- .../angle/src/compiler/translator/CodeGen.cpp | 14 +- .../angle/src/compiler/translator/Compiler.cpp | 234 +- .../angle/src/compiler/translator/Compiler.h | 191 + .../angle/src/compiler/translator/ConstantUnion.h | 94 +- .../src/compiler/translator/DetectCallDepth.h | 2 - .../angle/src/compiler/translator/Diagnostics.cpp | 2 +- .../angle/src/compiler/translator/Diagnostics.h | 2 +- .../src/compiler/translator/DirectiveHandler.cpp | 17 +- .../src/compiler/translator/DirectiveHandler.h | 4 +- .../src/compiler/translator/FlagStd140Structs.cpp | 77 + .../src/compiler/translator/FlagStd140Structs.h | 37 + .../src/compiler/translator/ForLoopUnroll.cpp | 245 +- .../angle/src/compiler/translator/ForLoopUnroll.h | 78 +- .../angle/src/compiler/translator/HashNames.h | 1 - .../angle/src/compiler/translator/Initialize.cpp | 983 +- .../angle/src/compiler/translator/Initialize.h | 6 +- .../src/compiler/translator/InitializeDll.cpp | 6 +- .../compiler/translator/InitializeParseContext.cpp | 26 +- .../compiler/translator/InitializeVariables.cpp | 24 +- .../src/compiler/translator/InitializeVariables.h | 16 +- .../src/compiler/translator/IntermTraverse.cpp | 120 +- .../angle/src/compiler/translator/Intermediate.cpp | 1915 ++-- .../angle/src/compiler/translator/LoopInfo.cpp | 211 + .../angle/src/compiler/translator/LoopInfo.h | 80 + .../compiler/translator/MapLongVariableNames.cpp | 115 - .../src/compiler/translator/MapLongVariableNames.h | 58 - .../angle/src/compiler/translator/OutputESSL.cpp | 7 +- .../angle/src/compiler/translator/OutputESSL.h | 5 +- .../angle/src/compiler/translator/OutputGLSL.cpp | 28 +- .../angle/src/compiler/translator/OutputGLSL.h | 6 +- .../src/compiler/translator/OutputGLSLBase.cpp | 1094 +- .../angle/src/compiler/translator/OutputGLSLBase.h | 82 +- .../angle/src/compiler/translator/OutputHLSL.cpp | 2762 +++-- .../angle/src/compiler/translator/OutputHLSL.h | 118 +- .../angle/src/compiler/translator/ParseContext.cpp | 1446 ++- .../angle/src/compiler/translator/ParseContext.h | 63 +- .../angle/src/compiler/translator/PoolAlloc.cpp | 35 +- .../angle/src/compiler/translator/RemoveTree.cpp | 70 +- .../src/compiler/translator/RewriteElseBlocks.cpp | 92 +- .../src/compiler/translator/RewriteElseBlocks.h | 17 - .../ScalarizeVecAndMatConstructorArgs.cpp | 266 + .../translator/ScalarizeVecAndMatConstructorArgs.h | 41 + .../angle/src/compiler/translator/ShHandle.h | 179 - .../angle/src/compiler/translator/ShaderLang.cpp | 234 +- .../src/compiler/translator/StructureHLSL.cpp | 477 + .../angle/src/compiler/translator/StructureHLSL.h | 74 + .../angle/src/compiler/translator/SymbolTable.cpp | 316 +- .../angle/src/compiler/translator/SymbolTable.h | 455 +- .../src/compiler/translator/TranslatorESSL.cpp | 11 +- .../angle/src/compiler/translator/TranslatorESSL.h | 4 +- .../src/compiler/translator/TranslatorGLSL.cpp | 30 +- .../angle/src/compiler/translator/TranslatorGLSL.h | 7 +- .../src/compiler/translator/TranslatorHLSL.cpp | 38 +- .../angle/src/compiler/translator/TranslatorHLSL.h | 25 +- .../angle/src/compiler/translator/Types.cpp | 202 + src/3rdparty/angle/src/compiler/translator/Types.h | 527 +- .../src/compiler/translator/UnfoldShortCircuit.cpp | 3 +- .../angle/src/compiler/translator/Uniform.cpp | 21 - .../angle/src/compiler/translator/Uniform.h | 35 - .../angle/src/compiler/translator/UniformHLSL.cpp | 291 + .../angle/src/compiler/translator/UniformHLSL.h | 66 + .../angle/src/compiler/translator/UtilsHLSL.cpp | 243 + .../angle/src/compiler/translator/UtilsHLSL.h | 37 + .../compiler/translator/ValidateLimitations.cpp | 428 +- .../src/compiler/translator/ValidateLimitations.h | 58 +- .../src/compiler/translator/ValidateOutputs.cpp | 78 + .../src/compiler/translator/ValidateOutputs.h | 33 + .../angle/src/compiler/translator/VariableInfo.cpp | 553 +- .../angle/src/compiler/translator/VariableInfo.h | 58 +- .../src/compiler/translator/VariablePacker.cpp | 190 +- .../angle/src/compiler/translator/VariablePacker.h | 14 +- .../angle/src/compiler/translator/VersionGLSL.cpp | 111 +- .../angle/src/compiler/translator/VersionGLSL.h | 32 +- .../translator/depgraph/DependencyGraphBuilder.cpp | 164 +- .../translator/depgraph/DependencyGraphBuilder.h | 194 +- .../angle/src/compiler/translator/glslang.l | 385 +- .../angle/src/compiler/translator/glslang.y | 757 +- .../angle/src/compiler/translator/intermOut.cpp | 608 +- .../angle/src/compiler/translator/intermediate.h | 626 +- .../angle/src/compiler/translator/length_limits.h | 21 + .../src/compiler/translator/localintermediate.h | 86 +- .../angle/src/compiler/translator/osinclude.h | 64 - .../src/compiler/translator/ossource_posix.cpp | 72 - .../angle/src/compiler/translator/ossource_win.cpp | 65 - .../src/compiler/translator/ossource_winrt.cpp | 75 - .../angle/src/compiler/translator/parseConst.cpp | 269 +- .../timing/RestrictFragmentShaderTiming.cpp | 9 + .../timing/RestrictFragmentShaderTiming.h | 2 - .../timing/RestrictVertexShaderTiming.cpp | 2 +- .../translator/timing/RestrictVertexShaderTiming.h | 2 - .../angle/src/compiler/translator/util.cpp | 328 + src/3rdparty/angle/src/compiler/translator/util.h | 46 + src/3rdparty/angle/src/libEGL/Config.cpp | 17 +- src/3rdparty/angle/src/libEGL/Config.h | 1 - src/3rdparty/angle/src/libEGL/Display.cpp | 192 +- src/3rdparty/angle/src/libEGL/Display.h | 23 +- src/3rdparty/angle/src/libEGL/Surface.cpp | 370 +- src/3rdparty/angle/src/libEGL/Surface.h | 54 +- src/3rdparty/angle/src/libEGL/libEGL.cpp | 1239 +-- src/3rdparty/angle/src/libEGL/libEGL.def | 75 +- src/3rdparty/angle/src/libEGL/libEGL_mingw32.def | 73 +- src/3rdparty/angle/src/libEGL/libEGLd.def | 75 +- src/3rdparty/angle/src/libEGL/libEGLd_mingw32.def | 73 +- src/3rdparty/angle/src/libEGL/main.cpp | 83 +- src/3rdparty/angle/src/libEGL/main.h | 1 + src/3rdparty/angle/src/libGLESv2/BinaryStream.h | 118 +- src/3rdparty/angle/src/libGLESv2/Buffer.cpp | 115 +- src/3rdparty/angle/src/libGLESv2/Buffer.h | 47 +- src/3rdparty/angle/src/libGLESv2/Caps.cpp | 363 + src/3rdparty/angle/src/libGLESv2/Caps.h | 222 + src/3rdparty/angle/src/libGLESv2/Context.cpp | 2999 +++-- src/3rdparty/angle/src/libGLESv2/Context.h | 478 +- src/3rdparty/angle/src/libGLESv2/DynamicHLSL.cpp | 1122 ++ src/3rdparty/angle/src/libGLESv2/DynamicHLSL.h | 96 + src/3rdparty/angle/src/libGLESv2/Fence.cpp | 165 +- src/3rdparty/angle/src/libGLESv2/Fence.h | 41 +- src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp | 535 +- src/3rdparty/angle/src/libGLESv2/Framebuffer.h | 62 +- .../angle/src/libGLESv2/FramebufferAttachment.cpp | 495 + .../angle/src/libGLESv2/FramebufferAttachment.h | 246 + src/3rdparty/angle/src/libGLESv2/HandleAllocator.h | 3 +- src/3rdparty/angle/src/libGLESv2/Program.cpp | 162 +- src/3rdparty/angle/src/libGLESv2/Program.h | 24 +- src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp | 3260 +++--- src/3rdparty/angle/src/libGLESv2/ProgramBinary.h | 243 +- src/3rdparty/angle/src/libGLESv2/Query.cpp | 5 + src/3rdparty/angle/src/libGLESv2/Query.h | 4 +- src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp | 317 +- src/3rdparty/angle/src/libGLESv2/Renderbuffer.h | 156 +- .../angle/src/libGLESv2/ResourceManager.cpp | 118 +- src/3rdparty/angle/src/libGLESv2/ResourceManager.h | 46 +- src/3rdparty/angle/src/libGLESv2/Sampler.cpp | 44 + src/3rdparty/angle/src/libGLESv2/Sampler.h | 60 + src/3rdparty/angle/src/libGLESv2/Shader.cpp | 529 +- src/3rdparty/angle/src/libGLESv2/Shader.h | 114 +- src/3rdparty/angle/src/libGLESv2/State.cpp | 1415 +++ src/3rdparty/angle/src/libGLESv2/State.h | 307 + src/3rdparty/angle/src/libGLESv2/Texture.cpp | 1491 +-- src/3rdparty/angle/src/libGLESv2/Texture.h | 298 +- .../angle/src/libGLESv2/TransformFeedback.cpp | 63 + .../angle/src/libGLESv2/TransformFeedback.h | 44 + src/3rdparty/angle/src/libGLESv2/Uniform.cpp | 91 +- src/3rdparty/angle/src/libGLESv2/Uniform.h | 47 +- src/3rdparty/angle/src/libGLESv2/VertexArray.cpp | 97 + src/3rdparty/angle/src/libGLESv2/VertexArray.h | 61 + .../angle/src/libGLESv2/VertexAttribute.cpp | 56 + src/3rdparty/angle/src/libGLESv2/VertexAttribute.h | 119 + src/3rdparty/angle/src/libGLESv2/angletypes.cpp | 196 + src/3rdparty/angle/src/libGLESv2/angletypes.h | 160 +- src/3rdparty/angle/src/libGLESv2/constants.h | 24 +- src/3rdparty/angle/src/libGLESv2/formatutils.cpp | 1548 +++ src/3rdparty/angle/src/libGLESv2/formatutils.h | 88 + src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp | 10888 +++++++++++-------- src/3rdparty/angle/src/libGLESv2/libGLESv2.def | 113 +- .../angle/src/libGLESv2/libGLESv2_mingw32.def | 477 +- src/3rdparty/angle/src/libGLESv2/libGLESv2d.def | 113 +- .../angle/src/libGLESv2/libGLESv2d_mingw32.def | 477 +- src/3rdparty/angle/src/libGLESv2/main.cpp | 86 +- src/3rdparty/angle/src/libGLESv2/main.h | 11 +- src/3rdparty/angle/src/libGLESv2/mathutil.h | 162 - src/3rdparty/angle/src/libGLESv2/precompiled.h | 63 +- .../angle/src/libGLESv2/queryconversions.cpp | 148 + .../angle/src/libGLESv2/queryconversions.h | 17 + .../angle/src/libGLESv2/renderer/BufferImpl.h | 34 + .../angle/src/libGLESv2/renderer/BufferStorage.cpp | 40 - .../angle/src/libGLESv2/renderer/BufferStorage.h | 44 - .../angle/src/libGLESv2/renderer/FenceImpl.h | 21 +- .../angle/src/libGLESv2/renderer/Image.cpp | 527 +- src/3rdparty/angle/src/libGLESv2/renderer/Image.h | 87 +- .../angle/src/libGLESv2/renderer/ImageSSE2.cpp | 100 - .../angle/src/libGLESv2/renderer/IndexBuffer.cpp | 197 - .../angle/src/libGLESv2/renderer/IndexBuffer.h | 111 - .../src/libGLESv2/renderer/IndexDataManager.cpp | 339 - .../src/libGLESv2/renderer/IndexDataManager.h | 66 - .../src/libGLESv2/renderer/IndexRangeCache.cpp | 4 +- .../angle/src/libGLESv2/renderer/IndexRangeCache.h | 3 +- .../angle/src/libGLESv2/renderer/QueryImpl.h | 1 + .../angle/src/libGLESv2/renderer/RenderTarget.h | 20 +- .../angle/src/libGLESv2/renderer/Renderer.cpp | 297 +- .../angle/src/libGLESv2/renderer/Renderer.h | 173 +- .../angle/src/libGLESv2/renderer/ShaderCache.h | 110 - .../src/libGLESv2/renderer/ShaderExecutable.h | 39 +- .../angle/src/libGLESv2/renderer/SwapChain.h | 14 +- .../angle/src/libGLESv2/renderer/TextureImpl.h | 166 + .../src/libGLESv2/renderer/TextureStorage.cpp | 122 - .../angle/src/libGLESv2/renderer/TextureStorage.h | 110 - .../angle/src/libGLESv2/renderer/VertexArrayImpl.h | 32 + .../angle/src/libGLESv2/renderer/VertexBuffer.cpp | 292 - .../angle/src/libGLESv2/renderer/VertexBuffer.h | 139 - .../src/libGLESv2/renderer/VertexDataManager.cpp | 304 - .../src/libGLESv2/renderer/VertexDataManager.h | 65 - .../angle/src/libGLESv2/renderer/copyimage.cpp | 23 + .../angle/src/libGLESv2/renderer/copyimage.h | 42 + .../angle/src/libGLESv2/renderer/copyvertex.h | 309 + .../angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp | 83 + .../angle/src/libGLESv2/renderer/d3d/BufferD3D.h | 60 + .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp | 171 + .../src/libGLESv2/renderer/d3d/HLSLCompiler.h | 38 + .../angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp | 27 + .../angle/src/libGLESv2/renderer/d3d/ImageD3D.h | 54 + .../src/libGLESv2/renderer/d3d/IndexBuffer.cpp | 196 + .../angle/src/libGLESv2/renderer/d3d/IndexBuffer.h | 111 + .../libGLESv2/renderer/d3d/IndexDataManager.cpp | 339 + .../src/libGLESv2/renderer/d3d/IndexDataManager.h | 66 + .../src/libGLESv2/renderer/d3d/MemoryBuffer.cpp | 72 + .../src/libGLESv2/renderer/d3d/MemoryBuffer.h | 35 + .../src/libGLESv2/renderer/d3d/TextureD3D.cpp | 2550 +++++ .../angle/src/libGLESv2/renderer/d3d/TextureD3D.h | 343 + .../src/libGLESv2/renderer/d3d/TextureStorage.cpp | 181 + .../src/libGLESv2/renderer/d3d/TextureStorage.h | 145 + .../src/libGLESv2/renderer/d3d/VertexBuffer.cpp | 296 + .../src/libGLESv2/renderer/d3d/VertexBuffer.h | 138 + .../libGLESv2/renderer/d3d/VertexDataManager.cpp | 299 + .../src/libGLESv2/renderer/d3d/VertexDataManager.h | 70 + .../src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp | 1049 ++ .../src/libGLESv2/renderer/d3d/d3d11/Blit11.h | 126 + .../src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp | 900 ++ .../src/libGLESv2/renderer/d3d/d3d11/Buffer11.h | 106 + .../src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp | 568 + .../src/libGLESv2/renderer/d3d/d3d11/Clear11.h | 83 + .../src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp | 71 + .../src/libGLESv2/renderer/d3d/d3d11/Fence11.h | 38 + .../src/libGLESv2/renderer/d3d/d3d11/Image11.cpp | 460 + .../src/libGLESv2/renderer/d3d/d3d11/Image11.h | 77 + .../libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp | 175 + .../libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h | 53 + .../renderer/d3d/d3d11/InputLayoutCache.cpp | 248 + .../renderer/d3d/d3d11/InputLayoutCache.h | 95 + .../renderer/d3d/d3d11/PixelTransfer11.cpp | 253 + .../libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h | 82 + .../src/libGLESv2/renderer/d3d/d3d11/Query11.cpp | 155 + .../src/libGLESv2/renderer/d3d/d3d11/Query11.h | 41 + .../renderer/d3d/d3d11/RenderStateCache.cpp | 436 + .../renderer/d3d/d3d11/RenderStateCache.h | 109 + .../renderer/d3d/d3d11/RenderTarget11.cpp | 457 + .../libGLESv2/renderer/d3d/d3d11/RenderTarget11.h | 54 + .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 3527 ++++++ .../src/libGLESv2/renderer/d3d/d3d11/Renderer11.h | 375 + .../renderer/d3d/d3d11/ShaderExecutable11.cpp | 112 + .../renderer/d3d/d3d11/ShaderExecutable11.h | 61 + .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp | 713 ++ .../src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h | 82 + .../renderer/d3d/d3d11/TextureStorage11.cpp | 1559 +++ .../renderer/d3d/d3d11/TextureStorage11.h | 278 + .../libGLESv2/renderer/d3d/d3d11/VertexArray11.h | 42 + .../renderer/d3d/d3d11/VertexBuffer11.cpp | 223 + .../libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h | 52 + .../libGLESv2/renderer/d3d/d3d11/formatutils11.cpp | 1458 +++ .../libGLESv2/renderer/d3d/d3d11/formatutils11.h | 79 + .../renderer/d3d/d3d11/renderer11_utils.cpp | 634 ++ .../renderer/d3d/d3d11/renderer11_utils.h | 173 + .../d3d/d3d11/shaders/BufferToTexture11.hlsl | 76 + .../renderer/d3d/d3d11/shaders/Clear11.hlsl | 106 + .../d3d/d3d11/shaders/Passthrough2D11.hlsl | 111 + .../d3d/d3d11/shaders/Passthrough3D11.hlsl | 146 + .../renderer/d3d/d3d11/shaders/Swizzle11.hlsl | 99 + .../src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp | 645 ++ .../angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h | 94 + .../src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp | 126 + .../src/libGLESv2/renderer/d3d/d3d9/Buffer9.h | 53 + .../src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp | 73 + .../angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h | 38 + .../src/libGLESv2/renderer/d3d/d3d9/Image9.cpp | 703 ++ .../angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h | 80 + .../libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp | 199 + .../src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h | 53 + .../src/libGLESv2/renderer/d3d/d3d9/Query9.cpp | 125 + .../angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h | 41 + .../libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp | 139 + .../libGLESv2/renderer/d3d/d3d9/RenderTarget9.h | 43 + .../src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 3254 ++++++ .../src/libGLESv2/renderer/d3d/d3d9/Renderer9.h | 364 + .../src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h | 102 + .../renderer/d3d/d3d9/ShaderExecutable9.cpp | 54 + .../renderer/d3d/d3d9/ShaderExecutable9.h | 39 + .../src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp | 416 + .../src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h | 55 + .../renderer/d3d/d3d9/TextureStorage9.cpp | 307 + .../libGLESv2/renderer/d3d/d3d9/TextureStorage9.h | 109 + .../src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h | 43 + .../libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp | 252 + .../libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h | 54 + .../renderer/d3d/d3d9/VertexDeclarationCache.cpp | 216 + .../renderer/d3d/d3d9/VertexDeclarationCache.h | 58 + .../libGLESv2/renderer/d3d/d3d9/formatutils9.cpp | 820 ++ .../src/libGLESv2/renderer/d3d/d3d9/formatutils9.h | 77 + .../renderer/d3d/d3d9/renderer9_utils.cpp | 409 + .../libGLESv2/renderer/d3d/d3d9/renderer9_utils.h | 65 + .../libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps | 33 + .../libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs | 43 + .../libGLESv2/renderer/d3d11/BufferStorage11.cpp | 366 - .../src/libGLESv2/renderer/d3d11/BufferStorage11.h | 92 - .../angle/src/libGLESv2/renderer/d3d11/Fence11.cpp | 134 - .../angle/src/libGLESv2/renderer/d3d11/Fence11.h | 39 - .../angle/src/libGLESv2/renderer/d3d11/Image11.cpp | 498 - .../angle/src/libGLESv2/renderer/d3d11/Image11.h | 76 - .../src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp | 183 - .../src/libGLESv2/renderer/d3d11/IndexBuffer11.h | 53 - .../libGLESv2/renderer/d3d11/InputLayoutCache.cpp | 213 - .../libGLESv2/renderer/d3d11/InputLayoutCache.h | 95 - .../angle/src/libGLESv2/renderer/d3d11/Query11.cpp | 122 - .../angle/src/libGLESv2/renderer/d3d11/Query11.h | 40 - .../libGLESv2/renderer/d3d11/RenderStateCache.cpp | 439 - .../libGLESv2/renderer/d3d11/RenderStateCache.h | 111 - .../libGLESv2/renderer/d3d11/RenderTarget11.cpp | 355 - .../src/libGLESv2/renderer/d3d11/RenderTarget11.h | 51 - .../src/libGLESv2/renderer/d3d11/Renderer11.cpp | 3736 ------- .../src/libGLESv2/renderer/d3d11/Renderer11.h | 373 - .../renderer/d3d11/ShaderExecutable11.cpp | 109 - .../libGLESv2/renderer/d3d11/ShaderExecutable11.h | 47 - .../src/libGLESv2/renderer/d3d11/SwapChain11.cpp | 700 -- .../src/libGLESv2/renderer/d3d11/SwapChain11.h | 78 - .../libGLESv2/renderer/d3d11/TextureStorage11.cpp | 667 -- .../libGLESv2/renderer/d3d11/TextureStorage11.h | 120 - .../libGLESv2/renderer/d3d11/VertexBuffer11.cpp | 440 - .../src/libGLESv2/renderer/d3d11/VertexBuffer11.h | 74 - .../libGLESv2/renderer/d3d11/renderer11_utils.cpp | 688 -- .../libGLESv2/renderer/d3d11/renderer11_utils.h | 95 - .../libGLESv2/renderer/d3d11/shaders/Clear11.hlsl | 42 - .../renderer/d3d11/shaders/Passthrough11.hlsl | 29 - .../angle/src/libGLESv2/renderer/d3d9/Blit.cpp | 595 - .../angle/src/libGLESv2/renderer/d3d9/Blit.h | 94 - .../src/libGLESv2/renderer/d3d9/BufferStorage9.cpp | 78 - .../src/libGLESv2/renderer/d3d9/BufferStorage9.h | 42 - .../angle/src/libGLESv2/renderer/d3d9/Fence9.cpp | 135 - .../angle/src/libGLESv2/renderer/d3d9/Fence9.h | 39 - .../angle/src/libGLESv2/renderer/d3d9/Image9.cpp | 736 -- .../angle/src/libGLESv2/renderer/d3d9/Image9.h | 79 - .../src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp | 207 - .../src/libGLESv2/renderer/d3d9/IndexBuffer9.h | 53 - .../angle/src/libGLESv2/renderer/d3d9/Query9.cpp | 125 - .../angle/src/libGLESv2/renderer/d3d9/Query9.h | 40 - .../src/libGLESv2/renderer/d3d9/RenderTarget9.cpp | 113 - .../src/libGLESv2/renderer/d3d9/RenderTarget9.h | 40 - .../src/libGLESv2/renderer/d3d9/Renderer9.cpp | 3287 ------ .../angle/src/libGLESv2/renderer/d3d9/Renderer9.h | 356 - .../libGLESv2/renderer/d3d9/ShaderExecutable9.cpp | 60 - .../libGLESv2/renderer/d3d9/ShaderExecutable9.h | 39 - .../src/libGLESv2/renderer/d3d9/SwapChain9.cpp | 445 - .../angle/src/libGLESv2/renderer/d3d9/SwapChain9.h | 55 - .../libGLESv2/renderer/d3d9/TextureStorage9.cpp | 328 - .../src/libGLESv2/renderer/d3d9/TextureStorage9.h | 109 - .../src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp | 530 - .../src/libGLESv2/renderer/d3d9/VertexBuffer9.h | 91 - .../renderer/d3d9/VertexDeclarationCache.cpp | 217 - .../renderer/d3d9/VertexDeclarationCache.h | 58 - .../libGLESv2/renderer/d3d9/renderer9_utils.cpp | 500 - .../src/libGLESv2/renderer/d3d9/renderer9_utils.h | 74 - .../src/libGLESv2/renderer/d3d9/shaders/Blit.ps | 39 - .../src/libGLESv2/renderer/d3d9/shaders/Blit.vs | 43 - .../src/libGLESv2/renderer/d3d9/vertexconversion.h | 203 - .../angle/src/libGLESv2/renderer/generatemip.h | 191 +- .../angle/src/libGLESv2/renderer/generatemip.inl | 266 + .../angle/src/libGLESv2/renderer/imageformats.h | 2029 ++++ .../angle/src/libGLESv2/renderer/loadimage.cpp | 662 ++ .../angle/src/libGLESv2/renderer/loadimage.h | 193 + .../angle/src/libGLESv2/renderer/loadimage.inl | 156 + .../angle/src/libGLESv2/renderer/loadimageSSE2.cpp | 113 + .../src/libGLESv2/renderer/vertexconversion.h | 203 + src/3rdparty/angle/src/libGLESv2/utilities.cpp | 817 -- src/3rdparty/angle/src/libGLESv2/utilities.h | 67 - src/3rdparty/angle/src/libGLESv2/validationES.cpp | 1583 +++ src/3rdparty/angle/src/libGLESv2/validationES.h | 75 + src/3rdparty/angle/src/libGLESv2/validationES2.cpp | 892 ++ src/3rdparty/angle/src/libGLESv2/validationES2.h | 32 + src/3rdparty/angle/src/libGLESv2/validationES3.cpp | 682 ++ src/3rdparty/angle/src/libGLESv2/validationES3.h | 40 + .../src/third_party/compiler/ArrayBoundsClamper.h | 2 - .../angle/src/third_party/murmurhash/MurmurHash3.h | 14 - .../src/third_party/systeminfo/SystemInfo.cpp | 60 + .../angle/src/third_party/systeminfo/SystemInfo.h | 35 + 428 files changed, 75879 insertions(+), 44124 deletions(-) create mode 100644 src/3rdparty/angle/include/GLES3/gl3.h create mode 100644 src/3rdparty/angle/include/GLES3/gl3ext.h create mode 100644 src/3rdparty/angle/include/GLES3/gl3platform.h create mode 100644 src/3rdparty/angle/include/angle_gl.h create mode 100644 src/3rdparty/angle/src/common/blocklayout.cpp create mode 100644 src/3rdparty/angle/src/common/blocklayout.h create mode 100644 src/3rdparty/angle/src/common/mathutil.cpp create mode 100644 src/3rdparty/angle/src/common/mathutil.h create mode 100644 src/3rdparty/angle/src/common/platform.h create mode 100644 src/3rdparty/angle/src/common/shadervars.h create mode 100644 src/3rdparty/angle/src/common/tls.cpp create mode 100644 src/3rdparty/angle/src/common/tls.h create mode 100644 src/3rdparty/angle/src/common/utilities.cpp create mode 100644 src/3rdparty/angle/src/common/utilities.h delete mode 100644 src/3rdparty/angle/src/compiler/preprocessor/length_limits.h create mode 100644 src/3rdparty/angle/src/compiler/translator/Compiler.h create mode 100644 src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h create mode 100644 src/3rdparty/angle/src/compiler/translator/LoopInfo.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/LoopInfo.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.h create mode 100644 src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ShHandle.h create mode 100644 src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/StructureHLSL.h create mode 100644 src/3rdparty/angle/src/compiler/translator/Types.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/Uniform.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/Uniform.h create mode 100644 src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/UniformHLSL.h create mode 100644 src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h create mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp create mode 100644 src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h create mode 100644 src/3rdparty/angle/src/compiler/translator/length_limits.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/osinclude.h delete mode 100644 src/3rdparty/angle/src/compiler/translator/ossource_posix.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ossource_win.cpp delete mode 100644 src/3rdparty/angle/src/compiler/translator/ossource_winrt.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/Caps.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/Caps.h create mode 100644 src/3rdparty/angle/src/libGLESv2/DynamicHLSL.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/DynamicHLSL.h create mode 100644 src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h create mode 100644 src/3rdparty/angle/src/libGLESv2/Sampler.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/Sampler.h create mode 100644 src/3rdparty/angle/src/libGLESv2/State.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/State.h create mode 100644 src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/TransformFeedback.h create mode 100644 src/3rdparty/angle/src/libGLESv2/VertexArray.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/VertexArray.h create mode 100644 src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/VertexAttribute.h create mode 100644 src/3rdparty/angle/src/libGLESv2/angletypes.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/formatutils.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/formatutils.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/mathutil.h create mode 100644 src/3rdparty/angle/src/libGLESv2/queryconversions.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/queryconversions.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ImageSSE2.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/ShaderCache.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs delete mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/d3d9/vertexconversion.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h delete mode 100644 src/3rdparty/angle/src/libGLESv2/utilities.cpp delete mode 100644 src/3rdparty/angle/src/libGLESv2/utilities.h create mode 100644 src/3rdparty/angle/src/libGLESv2/validationES.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/validationES.h create mode 100644 src/3rdparty/angle/src/libGLESv2/validationES2.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/validationES2.h create mode 100644 src/3rdparty/angle/src/libGLESv2/validationES3.cpp create mode 100644 src/3rdparty/angle/src/libGLESv2/validationES3.h create mode 100644 src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp create mode 100644 src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h (limited to 'src/3rdparty/angle') diff --git a/src/3rdparty/angle/.gitignore b/src/3rdparty/angle/.gitignore index b108d54d93..cbb7e6a5af 100644 --- a/src/3rdparty/angle/.gitignore +++ b/src/3rdparty/angle/.gitignore @@ -16,28 +16,17 @@ DEPS *.gypi *.sh *.bat +*.patch +*.py codereview.settings # Generated by flex/bison src/compiler/preprocessor/Tokenizer.cpp src/compiler/preprocessor/ExpressionParser.cpp -src/compiler/glslang_lex.cpp -src/compiler/glslang_tab.cpp -src/compiler/glslang_tab.h +src/compiler/translator/glslang_lex.cpp +src/compiler/translator/glslang_tab.cpp +src/compiler/translator/glslang_tab.h # Generated by FXC -src/libGLESv2/renderer/shaders/compiled/standardvs.h -src/libGLESv2/renderer/shaders/compiled/flipyvs.h -src/libGLESv2/renderer/shaders/compiled/luminanceps.h -src/libGLESv2/renderer/shaders/compiled/componentmaskps.h -src/libGLESv2/renderer/shaders/compiled/passthroughps.h -src/libGLESv2/renderer/shaders/compiled/PassthroughRGBA11ps.h -src/libGLESv2/renderer/shaders/compiled/PassthroughRGB11ps.h -src/libGLESv2/renderer/shaders/compiled/PassthroughLumAlpha11ps.h -src/libGLESv2/renderer/shaders/compiled/PassthroughLum11ps.h -src/libGLESv2/renderer/shaders/compiled/Passthrough11vs.h -src/libGLESv2/renderer/shaders/compiled/clear11vs.h -src/libGLESv2/renderer/shaders/compiled/clearmultiple11ps.h -src/libGLESv2/renderer/shaders/compiled/clearsingle11ps.h - - +src/libGLESv2/renderer/d3d/d3d9/shaders/compiled/*.h +src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/*.h diff --git a/src/3rdparty/angle/CONTRIBUTORS b/src/3rdparty/angle/CONTRIBUTORS index fcb6315234..7d152e7abf 100644 --- a/src/3rdparty/angle/CONTRIBUTORS +++ b/src/3rdparty/angle/CONTRIBUTORS @@ -52,6 +52,9 @@ Autodesk, Inc. Cloud Party, Inc. Conor Dickinson +Digia Plc + Andrew Knight + Intel Corporation Jin Yang Andy Chen diff --git a/src/3rdparty/angle/include/EGL/egl.h b/src/3rdparty/angle/include/EGL/egl.h index 99ea342a47..ab2f0cdfbe 100644 --- a/src/3rdparty/angle/include/EGL/egl.h +++ b/src/3rdparty/angle/include/EGL/egl.h @@ -1,11 +1,12 @@ -/* -*- mode: c; tab-width: 8; -*- */ -/* vi: set sw=4 ts=8: */ -/* Reference version of egl.h for EGL 1.4. - * $Revision: 9356 $ on $Date: 2009-10-21 02:52:25 -0700 (Wed, 21 Oct 2009) $ - */ +#ifndef __egl_h_ +#define __egl_h_ 1 + +#ifdef __cplusplus +extern "C" { +#endif /* -** Copyright (c) 2007-2009 The Khronos Group Inc. +** Copyright (c) 2013-2014 The Khronos Group Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a ** copy of this software and/or associated documentation files (the @@ -26,304 +27,272 @@ ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. */ +/* +** This header is generated from the Khronos OpenGL / OpenGL ES XML +** API Registry. The current version of the Registry, generator scripts +** used to make the header, and the header can be found at +** http://www.opengl.org/registry/ +** +** Khronos $Revision: 27018 $ on $Date: 2014-06-10 08:06:12 -0700 (Tue, 10 Jun 2014) $ +*/ -#ifndef __egl_h_ -#define __egl_h_ - -/* All platform-dependent types and macro boilerplate (such as EGLAPI - * and EGLAPIENTRY) should go in eglplatform.h. - */ #include -#ifdef __cplusplus -extern "C" { -#endif +/* Generated on date 20140610 */ + +/* Generated C header for: + * API: egl + * Versions considered: .* + * Versions emitted: .* + * Default extensions included: None + * Additional extensions included: _nomatch_^ + * Extensions removed: _nomatch_^ + */ -/* EGL Types */ -/* EGLint is defined in eglplatform.h */ +#ifndef EGL_VERSION_1_0 +#define EGL_VERSION_1_0 1 typedef unsigned int EGLBoolean; -typedef unsigned int EGLenum; -typedef void *EGLConfig; -typedef void *EGLContext; typedef void *EGLDisplay; +#include +#include +typedef void *EGLConfig; typedef void *EGLSurface; -typedef void *EGLClientBuffer; - -/* EGL Versioning */ -#define EGL_VERSION_1_0 1 -#define EGL_VERSION_1_1 1 -#define EGL_VERSION_1_2 1 -#define EGL_VERSION_1_3 1 -#define EGL_VERSION_1_4 1 - -/* EGL Enumerants. Bitmasks and other exceptional cases aside, most - * enums are assigned unique values starting at 0x3000. - */ - -/* EGL aliases */ -#define EGL_FALSE 0 -#define EGL_TRUE 1 - -/* Out-of-band handle values */ -#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0) -#define EGL_NO_CONTEXT ((EGLContext)0) -#define EGL_NO_DISPLAY ((EGLDisplay)0) -#define EGL_NO_SURFACE ((EGLSurface)0) - -/* Out-of-band attribute value */ -#define EGL_DONT_CARE ((EGLint)-1) - -/* Errors / GetError return values */ -#define EGL_SUCCESS 0x3000 -#define EGL_NOT_INITIALIZED 0x3001 -#define EGL_BAD_ACCESS 0x3002 -#define EGL_BAD_ALLOC 0x3003 -#define EGL_BAD_ATTRIBUTE 0x3004 -#define EGL_BAD_CONFIG 0x3005 -#define EGL_BAD_CONTEXT 0x3006 -#define EGL_BAD_CURRENT_SURFACE 0x3007 -#define EGL_BAD_DISPLAY 0x3008 -#define EGL_BAD_MATCH 0x3009 -#define EGL_BAD_NATIVE_PIXMAP 0x300A -#define EGL_BAD_NATIVE_WINDOW 0x300B -#define EGL_BAD_PARAMETER 0x300C -#define EGL_BAD_SURFACE 0x300D -#define EGL_CONTEXT_LOST 0x300E /* EGL 1.1 - IMG_power_management */ - -/* Reserved 0x300F-0x301F for additional errors */ - -/* Config attributes */ -#define EGL_BUFFER_SIZE 0x3020 -#define EGL_ALPHA_SIZE 0x3021 -#define EGL_BLUE_SIZE 0x3022 -#define EGL_GREEN_SIZE 0x3023 -#define EGL_RED_SIZE 0x3024 -#define EGL_DEPTH_SIZE 0x3025 -#define EGL_STENCIL_SIZE 0x3026 -#define EGL_CONFIG_CAVEAT 0x3027 -#define EGL_CONFIG_ID 0x3028 -#define EGL_LEVEL 0x3029 -#define EGL_MAX_PBUFFER_HEIGHT 0x302A -#define EGL_MAX_PBUFFER_PIXELS 0x302B -#define EGL_MAX_PBUFFER_WIDTH 0x302C -#define EGL_NATIVE_RENDERABLE 0x302D -#define EGL_NATIVE_VISUAL_ID 0x302E -#define EGL_NATIVE_VISUAL_TYPE 0x302F -#define EGL_SAMPLES 0x3031 -#define EGL_SAMPLE_BUFFERS 0x3032 -#define EGL_SURFACE_TYPE 0x3033 -#define EGL_TRANSPARENT_TYPE 0x3034 -#define EGL_TRANSPARENT_BLUE_VALUE 0x3035 -#define EGL_TRANSPARENT_GREEN_VALUE 0x3036 -#define EGL_TRANSPARENT_RED_VALUE 0x3037 -#define EGL_NONE 0x3038 /* Attrib list terminator */ -#define EGL_BIND_TO_TEXTURE_RGB 0x3039 -#define EGL_BIND_TO_TEXTURE_RGBA 0x303A -#define EGL_MIN_SWAP_INTERVAL 0x303B -#define EGL_MAX_SWAP_INTERVAL 0x303C -#define EGL_LUMINANCE_SIZE 0x303D -#define EGL_ALPHA_MASK_SIZE 0x303E -#define EGL_COLOR_BUFFER_TYPE 0x303F -#define EGL_RENDERABLE_TYPE 0x3040 -#define EGL_MATCH_NATIVE_PIXMAP 0x3041 /* Pseudo-attribute (not queryable) */ -#define EGL_CONFORMANT 0x3042 - -/* Reserved 0x3041-0x304F for additional config attributes */ - -/* Config attribute values */ -#define EGL_SLOW_CONFIG 0x3050 /* EGL_CONFIG_CAVEAT value */ -#define EGL_NON_CONFORMANT_CONFIG 0x3051 /* EGL_CONFIG_CAVEAT value */ -#define EGL_TRANSPARENT_RGB 0x3052 /* EGL_TRANSPARENT_TYPE value */ -#define EGL_RGB_BUFFER 0x308E /* EGL_COLOR_BUFFER_TYPE value */ -#define EGL_LUMINANCE_BUFFER 0x308F /* EGL_COLOR_BUFFER_TYPE value */ - -/* More config attribute values, for EGL_TEXTURE_FORMAT */ -#define EGL_NO_TEXTURE 0x305C -#define EGL_TEXTURE_RGB 0x305D -#define EGL_TEXTURE_RGBA 0x305E -#define EGL_TEXTURE_2D 0x305F - -/* Config attribute mask bits */ -#define EGL_PBUFFER_BIT 0x0001 /* EGL_SURFACE_TYPE mask bits */ -#define EGL_PIXMAP_BIT 0x0002 /* EGL_SURFACE_TYPE mask bits */ -#define EGL_WINDOW_BIT 0x0004 /* EGL_SURFACE_TYPE mask bits */ -#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020 /* EGL_SURFACE_TYPE mask bits */ -#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040 /* EGL_SURFACE_TYPE mask bits */ -#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200 /* EGL_SURFACE_TYPE mask bits */ -#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400 /* EGL_SURFACE_TYPE mask bits */ - -#define EGL_OPENGL_ES_BIT 0x0001 /* EGL_RENDERABLE_TYPE mask bits */ -#define EGL_OPENVG_BIT 0x0002 /* EGL_RENDERABLE_TYPE mask bits */ -#define EGL_OPENGL_ES2_BIT 0x0004 /* EGL_RENDERABLE_TYPE mask bits */ -#define EGL_OPENGL_BIT 0x0008 /* EGL_RENDERABLE_TYPE mask bits */ - -/* QueryString targets */ -#define EGL_VENDOR 0x3053 -#define EGL_VERSION 0x3054 -#define EGL_EXTENSIONS 0x3055 -#define EGL_CLIENT_APIS 0x308D - -/* QuerySurface / SurfaceAttrib / CreatePbufferSurface targets */ -#define EGL_HEIGHT 0x3056 -#define EGL_WIDTH 0x3057 -#define EGL_LARGEST_PBUFFER 0x3058 -#define EGL_TEXTURE_FORMAT 0x3080 -#define EGL_TEXTURE_TARGET 0x3081 -#define EGL_MIPMAP_TEXTURE 0x3082 -#define EGL_MIPMAP_LEVEL 0x3083 -#define EGL_RENDER_BUFFER 0x3086 -#define EGL_VG_COLORSPACE 0x3087 -#define EGL_VG_ALPHA_FORMAT 0x3088 -#define EGL_HORIZONTAL_RESOLUTION 0x3090 -#define EGL_VERTICAL_RESOLUTION 0x3091 -#define EGL_PIXEL_ASPECT_RATIO 0x3092 -#define EGL_SWAP_BEHAVIOR 0x3093 -#define EGL_MULTISAMPLE_RESOLVE 0x3099 - -/* EGL_RENDER_BUFFER values / BindTexImage / ReleaseTexImage buffer targets */ -#define EGL_BACK_BUFFER 0x3084 -#define EGL_SINGLE_BUFFER 0x3085 - -/* OpenVG color spaces */ -#define EGL_VG_COLORSPACE_sRGB 0x3089 /* EGL_VG_COLORSPACE value */ -#define EGL_VG_COLORSPACE_LINEAR 0x308A /* EGL_VG_COLORSPACE value */ - -/* OpenVG alpha formats */ -#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B /* EGL_ALPHA_FORMAT value */ -#define EGL_VG_ALPHA_FORMAT_PRE 0x308C /* EGL_ALPHA_FORMAT value */ - -/* Constant scale factor by which fractional display resolutions & - * aspect ratio are scaled when queried as integer values. - */ -#define EGL_DISPLAY_SCALING 10000 - -/* Unknown display resolution/aspect ratio */ -#define EGL_UNKNOWN ((EGLint)-1) - -/* Back buffer swap behaviors */ -#define EGL_BUFFER_PRESERVED 0x3094 /* EGL_SWAP_BEHAVIOR value */ -#define EGL_BUFFER_DESTROYED 0x3095 /* EGL_SWAP_BEHAVIOR value */ - -/* CreatePbufferFromClientBuffer buffer types */ -#define EGL_OPENVG_IMAGE 0x3096 - -/* QueryContext targets */ -#define EGL_CONTEXT_CLIENT_TYPE 0x3097 - -/* CreateContext attributes */ -#define EGL_CONTEXT_CLIENT_VERSION 0x3098 - -/* Multisample resolution behaviors */ -#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A /* EGL_MULTISAMPLE_RESOLVE value */ -#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B /* EGL_MULTISAMPLE_RESOLVE value */ - -/* BindAPI/QueryAPI targets */ -#define EGL_OPENGL_ES_API 0x30A0 -#define EGL_OPENVG_API 0x30A1 -#define EGL_OPENGL_API 0x30A2 - -/* GetCurrentSurface targets */ -#define EGL_DRAW 0x3059 -#define EGL_READ 0x305A - -/* WaitNative engines */ -#define EGL_CORE_NATIVE_ENGINE 0x305B - -/* EGL 1.2 tokens renamed for consistency in EGL 1.3 */ -#define EGL_COLORSPACE EGL_VG_COLORSPACE -#define EGL_ALPHA_FORMAT EGL_VG_ALPHA_FORMAT -#define EGL_COLORSPACE_sRGB EGL_VG_COLORSPACE_sRGB -#define EGL_COLORSPACE_LINEAR EGL_VG_COLORSPACE_LINEAR -#define EGL_ALPHA_FORMAT_NONPRE EGL_VG_ALPHA_FORMAT_NONPRE -#define EGL_ALPHA_FORMAT_PRE EGL_VG_ALPHA_FORMAT_PRE - -/* EGL extensions must request enum blocks from the Khronos - * API Registrar, who maintains the enumerant registry. Submit - * a bug in Khronos Bugzilla against task "Registry". - */ - - - -/* EGL Functions */ - -EGLAPI EGLint EGLAPIENTRY eglGetError(void); - -EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id); -EGLAPI EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor); -EGLAPI EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy); - -EGLAPI const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name); - -EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, - EGLint config_size, EGLint *num_config); -EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, - EGLConfig *configs, EGLint config_size, - EGLint *num_config); -EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, - EGLint attribute, EGLint *value); - -EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, - EGLNativeWindowType win, - const EGLint *attrib_list); -EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, - const EGLint *attrib_list); -EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, - EGLNativePixmapType pixmap, - const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface); -EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, - EGLint attribute, EGLint *value); - -EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api); -EGLAPI EGLenum EGLAPIENTRY eglQueryAPI(void); - -EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient(void); - -EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread(void); - -EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer( - EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, - EGLConfig config, const EGLint *attrib_list); - -EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, - EGLint attribute, EGLint value); -EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer); -EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer); - - -EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval); - - -EGLAPI EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, - EGLContext share_context, - const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx); -EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, - EGLSurface read, EGLContext ctx); - -EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext(void); -EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw); -EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void); -EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, - EGLint attribute, EGLint *value); - -EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL(void); -EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine); -EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface); -EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, - EGLNativePixmapType target); - -/* This is a generic function pointer type, whose name indicates it must - * be cast to the proper type *and calling convention* before use. - */ +typedef void *EGLContext; typedef void (*__eglMustCastToProperFunctionPointerType)(void); - -/* Now, define eglGetProcAddress using the generic function ptr. type */ -EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY - eglGetProcAddress(const char *procname); +#define EGL_ALPHA_SIZE 0x3021 +#define EGL_BAD_ACCESS 0x3002 +#define EGL_BAD_ALLOC 0x3003 +#define EGL_BAD_ATTRIBUTE 0x3004 +#define EGL_BAD_CONFIG 0x3005 +#define EGL_BAD_CONTEXT 0x3006 +#define EGL_BAD_CURRENT_SURFACE 0x3007 +#define EGL_BAD_DISPLAY 0x3008 +#define EGL_BAD_MATCH 0x3009 +#define EGL_BAD_NATIVE_PIXMAP 0x300A +#define EGL_BAD_NATIVE_WINDOW 0x300B +#define EGL_BAD_PARAMETER 0x300C +#define EGL_BAD_SURFACE 0x300D +#define EGL_BLUE_SIZE 0x3022 +#define EGL_BUFFER_SIZE 0x3020 +#define EGL_CONFIG_CAVEAT 0x3027 +#define EGL_CONFIG_ID 0x3028 +#define EGL_CORE_NATIVE_ENGINE 0x305B +#define EGL_DEPTH_SIZE 0x3025 +#define EGL_DONT_CARE ((EGLint)-1) +#define EGL_DRAW 0x3059 +#define EGL_EXTENSIONS 0x3055 +#define EGL_FALSE 0 +#define EGL_GREEN_SIZE 0x3023 +#define EGL_HEIGHT 0x3056 +#define EGL_LARGEST_PBUFFER 0x3058 +#define EGL_LEVEL 0x3029 +#define EGL_MAX_PBUFFER_HEIGHT 0x302A +#define EGL_MAX_PBUFFER_PIXELS 0x302B +#define EGL_MAX_PBUFFER_WIDTH 0x302C +#define EGL_NATIVE_RENDERABLE 0x302D +#define EGL_NATIVE_VISUAL_ID 0x302E +#define EGL_NATIVE_VISUAL_TYPE 0x302F +#define EGL_NONE 0x3038 +#define EGL_NON_CONFORMANT_CONFIG 0x3051 +#define EGL_NOT_INITIALIZED 0x3001 +#define EGL_NO_CONTEXT ((EGLContext)0) +#define EGL_NO_DISPLAY ((EGLDisplay)0) +#define EGL_NO_SURFACE ((EGLSurface)0) +#define EGL_PBUFFER_BIT 0x0001 +#define EGL_PIXMAP_BIT 0x0002 +#define EGL_READ 0x305A +#define EGL_RED_SIZE 0x3024 +#define EGL_SAMPLES 0x3031 +#define EGL_SAMPLE_BUFFERS 0x3032 +#define EGL_SLOW_CONFIG 0x3050 +#define EGL_STENCIL_SIZE 0x3026 +#define EGL_SUCCESS 0x3000 +#define EGL_SURFACE_TYPE 0x3033 +#define EGL_TRANSPARENT_BLUE_VALUE 0x3035 +#define EGL_TRANSPARENT_GREEN_VALUE 0x3036 +#define EGL_TRANSPARENT_RED_VALUE 0x3037 +#define EGL_TRANSPARENT_RGB 0x3052 +#define EGL_TRANSPARENT_TYPE 0x3034 +#define EGL_TRUE 1 +#define EGL_VENDOR 0x3053 +#define EGL_VERSION 0x3054 +#define EGL_WIDTH 0x3057 +#define EGL_WINDOW_BIT 0x0004 +EGLAPI EGLBoolean EGLAPIENTRY eglChooseConfig (EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); +EGLAPI EGLBoolean EGLAPIENTRY eglCopyBuffers (EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target); +EGLAPI EGLContext EGLAPIENTRY eglCreateContext (EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferSurface (EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurface (EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreateWindowSurface (EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyContext (EGLDisplay dpy, EGLContext ctx); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySurface (EGLDisplay dpy, EGLSurface surface); +EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigAttrib (EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value); +EGLAPI EGLBoolean EGLAPIENTRY eglGetConfigs (EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config); +EGLAPI EGLDisplay EGLAPIENTRY eglGetCurrentDisplay (void); +EGLAPI EGLSurface EGLAPIENTRY eglGetCurrentSurface (EGLint readdraw); +EGLAPI EGLDisplay EGLAPIENTRY eglGetDisplay (EGLNativeDisplayType display_id); +EGLAPI EGLint EGLAPIENTRY eglGetError (void); +EGLAPI __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress (const char *procname); +EGLAPI EGLBoolean EGLAPIENTRY eglInitialize (EGLDisplay dpy, EGLint *major, EGLint *minor); +EGLAPI EGLBoolean EGLAPIENTRY eglMakeCurrent (EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryContext (EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value); +EGLAPI const char *EGLAPIENTRY eglQueryString (EGLDisplay dpy, EGLint name); +EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value); +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffers (EGLDisplay dpy, EGLSurface surface); +EGLAPI EGLBoolean EGLAPIENTRY eglTerminate (EGLDisplay dpy); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitGL (void); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitNative (EGLint engine); +#endif /* EGL_VERSION_1_0 */ + +#ifndef EGL_VERSION_1_1 +#define EGL_VERSION_1_1 1 +#define EGL_BACK_BUFFER 0x3084 +#define EGL_BIND_TO_TEXTURE_RGB 0x3039 +#define EGL_BIND_TO_TEXTURE_RGBA 0x303A +#define EGL_CONTEXT_LOST 0x300E +#define EGL_MIN_SWAP_INTERVAL 0x303B +#define EGL_MAX_SWAP_INTERVAL 0x303C +#define EGL_MIPMAP_TEXTURE 0x3082 +#define EGL_MIPMAP_LEVEL 0x3083 +#define EGL_NO_TEXTURE 0x305C +#define EGL_TEXTURE_2D 0x305F +#define EGL_TEXTURE_FORMAT 0x3080 +#define EGL_TEXTURE_RGB 0x305D +#define EGL_TEXTURE_RGBA 0x305E +#define EGL_TEXTURE_TARGET 0x3081 +EGLAPI EGLBoolean EGLAPIENTRY eglBindTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer); +EGLAPI EGLBoolean EGLAPIENTRY eglReleaseTexImage (EGLDisplay dpy, EGLSurface surface, EGLint buffer); +EGLAPI EGLBoolean EGLAPIENTRY eglSurfaceAttrib (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value); +EGLAPI EGLBoolean EGLAPIENTRY eglSwapInterval (EGLDisplay dpy, EGLint interval); +#endif /* EGL_VERSION_1_1 */ + +#ifndef EGL_VERSION_1_2 +#define EGL_VERSION_1_2 1 +typedef unsigned int EGLenum; +typedef void *EGLClientBuffer; +#define EGL_ALPHA_FORMAT 0x3088 +#define EGL_ALPHA_FORMAT_NONPRE 0x308B +#define EGL_ALPHA_FORMAT_PRE 0x308C +#define EGL_ALPHA_MASK_SIZE 0x303E +#define EGL_BUFFER_PRESERVED 0x3094 +#define EGL_BUFFER_DESTROYED 0x3095 +#define EGL_CLIENT_APIS 0x308D +#define EGL_COLORSPACE 0x3087 +#define EGL_COLORSPACE_sRGB 0x3089 +#define EGL_COLORSPACE_LINEAR 0x308A +#define EGL_COLOR_BUFFER_TYPE 0x303F +#define EGL_CONTEXT_CLIENT_TYPE 0x3097 +#define EGL_DISPLAY_SCALING 10000 +#define EGL_HORIZONTAL_RESOLUTION 0x3090 +#define EGL_LUMINANCE_BUFFER 0x308F +#define EGL_LUMINANCE_SIZE 0x303D +#define EGL_OPENGL_ES_BIT 0x0001 +#define EGL_OPENVG_BIT 0x0002 +#define EGL_OPENGL_ES_API 0x30A0 +#define EGL_OPENVG_API 0x30A1 +#define EGL_OPENVG_IMAGE 0x3096 +#define EGL_PIXEL_ASPECT_RATIO 0x3092 +#define EGL_RENDERABLE_TYPE 0x3040 +#define EGL_RENDER_BUFFER 0x3086 +#define EGL_RGB_BUFFER 0x308E +#define EGL_SINGLE_BUFFER 0x3085 +#define EGL_SWAP_BEHAVIOR 0x3093 +#define EGL_UNKNOWN ((EGLint)-1) +#define EGL_VERTICAL_RESOLUTION 0x3091 +EGLAPI EGLBoolean EGLAPIENTRY eglBindAPI (EGLenum api); +EGLAPI EGLenum EGLAPIENTRY eglQueryAPI (void); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer (EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglReleaseThread (void); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitClient (void); +#endif /* EGL_VERSION_1_2 */ + +#ifndef EGL_VERSION_1_3 +#define EGL_VERSION_1_3 1 +#define EGL_CONFORMANT 0x3042 +#define EGL_CONTEXT_CLIENT_VERSION 0x3098 +#define EGL_MATCH_NATIVE_PIXMAP 0x3041 +#define EGL_OPENGL_ES2_BIT 0x0004 +#define EGL_VG_ALPHA_FORMAT 0x3088 +#define EGL_VG_ALPHA_FORMAT_NONPRE 0x308B +#define EGL_VG_ALPHA_FORMAT_PRE 0x308C +#define EGL_VG_ALPHA_FORMAT_PRE_BIT 0x0040 +#define EGL_VG_COLORSPACE 0x3087 +#define EGL_VG_COLORSPACE_sRGB 0x3089 +#define EGL_VG_COLORSPACE_LINEAR 0x308A +#define EGL_VG_COLORSPACE_LINEAR_BIT 0x0020 +#endif /* EGL_VERSION_1_3 */ + +#ifndef EGL_VERSION_1_4 +#define EGL_VERSION_1_4 1 +#define EGL_DEFAULT_DISPLAY ((EGLNativeDisplayType)0) +#define EGL_MULTISAMPLE_RESOLVE_BOX_BIT 0x0200 +#define EGL_MULTISAMPLE_RESOLVE 0x3099 +#define EGL_MULTISAMPLE_RESOLVE_DEFAULT 0x309A +#define EGL_MULTISAMPLE_RESOLVE_BOX 0x309B +#define EGL_OPENGL_API 0x30A2 +#define EGL_OPENGL_BIT 0x0008 +#define EGL_SWAP_BEHAVIOR_PRESERVED_BIT 0x0400 +EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void); +#endif /* EGL_VERSION_1_4 */ + +#ifndef EGL_VERSION_1_5 +#define EGL_VERSION_1_5 1 +typedef void *EGLSync; +typedef khronos_intptr_t EGLAttrib; +typedef khronos_utime_nanoseconds_t EGLTime; +#define EGL_CONTEXT_MAJOR_VERSION 0x3098 +#define EGL_CONTEXT_MINOR_VERSION 0x30FB +#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD +#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY 0x31BD +#define EGL_NO_RESET_NOTIFICATION 0x31BE +#define EGL_LOSE_CONTEXT_ON_RESET 0x31BF +#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT 0x00000001 +#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT 0x00000002 +#define EGL_CONTEXT_OPENGL_DEBUG 0x31B0 +#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE 0x31B1 +#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS 0x31B2 +#define EGL_OPENGL_ES3_BIT 0x00000040 +#define EGL_CL_EVENT_HANDLE 0x309C +#define EGL_SYNC_CL_EVENT 0x30FE +#define EGL_SYNC_CL_EVENT_COMPLETE 0x30FF +#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE 0x30F0 +#define EGL_SYNC_TYPE 0x30F7 +#define EGL_SYNC_STATUS 0x30F1 +#define EGL_SYNC_CONDITION 0x30F8 +#define EGL_SIGNALED 0x30F2 +#define EGL_UNSIGNALED 0x30F3 +#define EGL_SYNC_FLUSH_COMMANDS_BIT 0x0001 +#define EGL_FOREVER 0xFFFFFFFFFFFFFFFFull +#define EGL_TIMEOUT_EXPIRED 0x30F5 +#define EGL_CONDITION_SATISFIED 0x30F6 +#define EGL_NO_SYNC ((EGLSync)0) +#define EGL_SYNC_FENCE 0x30F9 +#define EGL_GL_COLORSPACE 0x309D +#define EGL_GL_COLORSPACE_SRGB 0x3089 +#define EGL_GL_COLORSPACE_LINEAR 0x308A +#define EGL_GL_RENDERBUFFER 0x30B9 +#define EGL_GL_TEXTURE_2D 0x30B1 +#define EGL_GL_TEXTURE_LEVEL 0x30BC +#define EGL_GL_TEXTURE_3D 0x30B2 +#define EGL_GL_TEXTURE_ZOFFSET 0x30BD +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x30B3 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x30B4 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x30B5 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8 +EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync); +EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout); +EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value); +EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags); +#endif /* EGL_VERSION_1_5 */ #ifdef __cplusplus } #endif -#endif /* __egl_h_ */ +#endif diff --git a/src/3rdparty/angle/include/EGL/eglext.h b/src/3rdparty/angle/include/EGL/eglext.h index c06d4c0850..989359b026 100644 --- a/src/3rdparty/angle/include/EGL/eglext.h +++ b/src/3rdparty/angle/include/EGL/eglext.h @@ -1,12 +1,12 @@ #ifndef __eglext_h_ -#define __eglext_h_ +#define __eglext_h_ 1 #ifdef __cplusplus extern "C" { #endif /* -** Copyright (c) 2007-2012 The Khronos Group Inc. +** Copyright (c) 2013-2014 The Khronos Group Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a ** copy of this software and/or associated documentation files (the @@ -27,325 +27,729 @@ extern "C" { ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. */ +/* +** This header is generated from the Khronos OpenGL / OpenGL ES XML +** API Registry. The current version of the Registry, generator scripts +** used to make the header, and the header can be found at +** http://www.opengl.org/registry/ +** +** Khronos $Revision: 27018 $ on $Date: 2014-06-10 08:06:12 -0700 (Tue, 10 Jun 2014) $ +*/ #include -/*************************************************************/ +#define EGL_EGLEXT_VERSION 20140610 -/* Header file version number */ -/* Current version at http://www.khronos.org/registry/egl/ */ -/* $Revision: 16473 $ on $Date: 2012-01-04 02:20:48 -0800 (Wed, 04 Jan 2012) $ */ -#define EGL_EGLEXT_VERSION 11 +/* Generated C header for: + * API: egl + * Versions considered: .* + * Versions emitted: _nomatch_^ + * Default extensions included: egl + * Additional extensions included: _nomatch_^ + * Extensions removed: _nomatch_^ + */ + +#ifndef EGL_KHR_cl_event +#define EGL_KHR_cl_event 1 +#define EGL_CL_EVENT_HANDLE_KHR 0x309C +#define EGL_SYNC_CL_EVENT_KHR 0x30FE +#define EGL_SYNC_CL_EVENT_COMPLETE_KHR 0x30FF +#endif /* EGL_KHR_cl_event */ + +#ifndef EGL_KHR_cl_event2 +#define EGL_KHR_cl_event2 1 +typedef void *EGLSyncKHR; +typedef khronos_intptr_t EGLAttribKHR; +typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNC64KHRPROC) (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSync64KHR (EGLDisplay dpy, EGLenum type, const EGLAttribKHR *attrib_list); +#endif +#endif /* EGL_KHR_cl_event2 */ + +#ifndef EGL_KHR_client_get_all_proc_addresses +#define EGL_KHR_client_get_all_proc_addresses 1 +#endif /* EGL_KHR_client_get_all_proc_addresses */ #ifndef EGL_KHR_config_attribs #define EGL_KHR_config_attribs 1 -#define EGL_CONFORMANT_KHR 0x3042 /* EGLConfig attribute */ -#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020 /* EGL_SURFACE_TYPE bitfield */ -#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040 /* EGL_SURFACE_TYPE bitfield */ -#endif +#define EGL_CONFORMANT_KHR 0x3042 +#define EGL_VG_COLORSPACE_LINEAR_BIT_KHR 0x0020 +#define EGL_VG_ALPHA_FORMAT_PRE_BIT_KHR 0x0040 +#endif /* EGL_KHR_config_attribs */ + +#ifndef EGL_KHR_create_context +#define EGL_KHR_create_context 1 +#define EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098 +#define EGL_CONTEXT_MINOR_VERSION_KHR 0x30FB +#define EGL_CONTEXT_FLAGS_KHR 0x30FC +#define EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR 0x30FD +#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR 0x31BD +#define EGL_NO_RESET_NOTIFICATION_KHR 0x31BE +#define EGL_LOSE_CONTEXT_ON_RESET_KHR 0x31BF +#define EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 0x00000001 +#define EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 0x00000002 +#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR 0x00000004 +#define EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 0x00000001 +#define EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR 0x00000002 +#define EGL_OPENGL_ES3_BIT_KHR 0x00000040 +#endif /* EGL_KHR_create_context */ -#ifndef EGL_KHR_lock_surface -#define EGL_KHR_lock_surface 1 -#define EGL_READ_SURFACE_BIT_KHR 0x0001 /* EGL_LOCK_USAGE_HINT_KHR bitfield */ -#define EGL_WRITE_SURFACE_BIT_KHR 0x0002 /* EGL_LOCK_USAGE_HINT_KHR bitfield */ -#define EGL_LOCK_SURFACE_BIT_KHR 0x0080 /* EGL_SURFACE_TYPE bitfield */ -#define EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100 /* EGL_SURFACE_TYPE bitfield */ -#define EGL_MATCH_FORMAT_KHR 0x3043 /* EGLConfig attribute */ -#define EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0 /* EGL_MATCH_FORMAT_KHR value */ -#define EGL_FORMAT_RGB_565_KHR 0x30C1 /* EGL_MATCH_FORMAT_KHR value */ -#define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2 /* EGL_MATCH_FORMAT_KHR value */ -#define EGL_FORMAT_RGBA_8888_KHR 0x30C3 /* EGL_MATCH_FORMAT_KHR value */ -#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4 /* eglLockSurfaceKHR attribute */ -#define EGL_LOCK_USAGE_HINT_KHR 0x30C5 /* eglLockSurfaceKHR attribute */ -#define EGL_BITMAP_POINTER_KHR 0x30C6 /* eglQuerySurface attribute */ -#define EGL_BITMAP_PITCH_KHR 0x30C7 /* eglQuerySurface attribute */ -#define EGL_BITMAP_ORIGIN_KHR 0x30C8 /* eglQuerySurface attribute */ -#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9 /* eglQuerySurface attribute */ -#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA /* eglQuerySurface attribute */ -#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB /* eglQuerySurface attribute */ -#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC /* eglQuerySurface attribute */ -#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD /* eglQuerySurface attribute */ -#define EGL_LOWER_LEFT_KHR 0x30CE /* EGL_BITMAP_ORIGIN_KHR value */ -#define EGL_UPPER_LEFT_KHR 0x30CF /* EGL_BITMAP_ORIGIN_KHR value */ -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay display, EGLSurface surface); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface, const EGLint *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay display, EGLSurface surface); -#endif +#ifndef EGL_KHR_fence_sync +#define EGL_KHR_fence_sync 1 +#ifdef KHRONOS_SUPPORT_INT64 +#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0 +#define EGL_SYNC_CONDITION_KHR 0x30F8 +#define EGL_SYNC_FENCE_KHR 0x30F9 +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_KHR_fence_sync */ + +#ifndef EGL_KHR_get_all_proc_addresses +#define EGL_KHR_get_all_proc_addresses 1 +#endif /* EGL_KHR_get_all_proc_addresses */ + +#ifndef EGL_KHR_gl_colorspace +#define EGL_KHR_gl_colorspace 1 +#define EGL_GL_COLORSPACE_KHR 0x309D +#define EGL_GL_COLORSPACE_SRGB_KHR 0x3089 +#define EGL_GL_COLORSPACE_LINEAR_KHR 0x308A +#endif /* EGL_KHR_gl_colorspace */ + +#ifndef EGL_KHR_gl_renderbuffer_image +#define EGL_KHR_gl_renderbuffer_image 1 +#define EGL_GL_RENDERBUFFER_KHR 0x30B9 +#endif /* EGL_KHR_gl_renderbuffer_image */ + +#ifndef EGL_KHR_gl_texture_2D_image +#define EGL_KHR_gl_texture_2D_image 1 +#define EGL_GL_TEXTURE_2D_KHR 0x30B1 +#define EGL_GL_TEXTURE_LEVEL_KHR 0x30BC +#endif /* EGL_KHR_gl_texture_2D_image */ + +#ifndef EGL_KHR_gl_texture_3D_image +#define EGL_KHR_gl_texture_3D_image 1 +#define EGL_GL_TEXTURE_3D_KHR 0x30B2 +#define EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD +#endif /* EGL_KHR_gl_texture_3D_image */ + +#ifndef EGL_KHR_gl_texture_cubemap_image +#define EGL_KHR_gl_texture_cubemap_image 1 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6 +#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7 +#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8 +#endif /* EGL_KHR_gl_texture_cubemap_image */ #ifndef EGL_KHR_image #define EGL_KHR_image 1 -#define EGL_NATIVE_PIXMAP_KHR 0x30B0 /* eglCreateImageKHR target */ typedef void *EGLImageKHR; -#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0) +#define EGL_NATIVE_PIXMAP_KHR 0x30B0 +#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0) +typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image); #ifdef EGL_EGLEXT_PROTOTYPES EGLAPI EGLImageKHR EGLAPIENTRY eglCreateImageKHR (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImageKHR (EGLDisplay dpy, EGLImageKHR image); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay dpy, EGLImageKHR image); #endif +#endif /* EGL_KHR_image */ -#ifndef EGL_KHR_vg_parent_image -#define EGL_KHR_vg_parent_image 1 -#define EGL_VG_PARENT_IMAGE_KHR 0x30BA /* eglCreateImageKHR target */ -#endif +#ifndef EGL_KHR_image_base +#define EGL_KHR_image_base 1 +#define EGL_IMAGE_PRESERVED_KHR 0x30D2 +#endif /* EGL_KHR_image_base */ -#ifndef EGL_KHR_gl_texture_2D_image -#define EGL_KHR_gl_texture_2D_image 1 -#define EGL_GL_TEXTURE_2D_KHR 0x30B1 /* eglCreateImageKHR target */ -#define EGL_GL_TEXTURE_LEVEL_KHR 0x30BC /* eglCreateImageKHR attribute */ -#endif +#ifndef EGL_KHR_image_pixmap +#define EGL_KHR_image_pixmap 1 +#endif /* EGL_KHR_image_pixmap */ -#ifndef EGL_KHR_gl_texture_cubemap_image -#define EGL_KHR_gl_texture_cubemap_image 1 -#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X_KHR 0x30B3 /* eglCreateImageKHR target */ -#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X_KHR 0x30B4 /* eglCreateImageKHR target */ -#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y_KHR 0x30B5 /* eglCreateImageKHR target */ -#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_KHR 0x30B6 /* eglCreateImageKHR target */ -#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z_KHR 0x30B7 /* eglCreateImageKHR target */ -#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_KHR 0x30B8 /* eglCreateImageKHR target */ +#ifndef EGL_KHR_lock_surface +#define EGL_KHR_lock_surface 1 +#define EGL_READ_SURFACE_BIT_KHR 0x0001 +#define EGL_WRITE_SURFACE_BIT_KHR 0x0002 +#define EGL_LOCK_SURFACE_BIT_KHR 0x0080 +#define EGL_OPTIMAL_FORMAT_BIT_KHR 0x0100 +#define EGL_MATCH_FORMAT_KHR 0x3043 +#define EGL_FORMAT_RGB_565_EXACT_KHR 0x30C0 +#define EGL_FORMAT_RGB_565_KHR 0x30C1 +#define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2 +#define EGL_FORMAT_RGBA_8888_KHR 0x30C3 +#define EGL_MAP_PRESERVE_PIXELS_KHR 0x30C4 +#define EGL_LOCK_USAGE_HINT_KHR 0x30C5 +#define EGL_BITMAP_POINTER_KHR 0x30C6 +#define EGL_BITMAP_PITCH_KHR 0x30C7 +#define EGL_BITMAP_ORIGIN_KHR 0x30C8 +#define EGL_BITMAP_PIXEL_RED_OFFSET_KHR 0x30C9 +#define EGL_BITMAP_PIXEL_GREEN_OFFSET_KHR 0x30CA +#define EGL_BITMAP_PIXEL_BLUE_OFFSET_KHR 0x30CB +#define EGL_BITMAP_PIXEL_ALPHA_OFFSET_KHR 0x30CC +#define EGL_BITMAP_PIXEL_LUMINANCE_OFFSET_KHR 0x30CD +#define EGL_LOWER_LEFT_KHR 0x30CE +#define EGL_UPPER_LEFT_KHR 0x30CF +typedef EGLBoolean (EGLAPIENTRYP PFNEGLLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLUNLOCKSURFACEKHRPROC) (EGLDisplay dpy, EGLSurface surface); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglLockSurfaceKHR (EGLDisplay dpy, EGLSurface surface, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglUnlockSurfaceKHR (EGLDisplay dpy, EGLSurface surface); #endif +#endif /* EGL_KHR_lock_surface */ -#ifndef EGL_KHR_gl_texture_3D_image -#define EGL_KHR_gl_texture_3D_image 1 -#define EGL_GL_TEXTURE_3D_KHR 0x30B2 /* eglCreateImageKHR target */ -#define EGL_GL_TEXTURE_ZOFFSET_KHR 0x30BD /* eglCreateImageKHR attribute */ -#endif +#ifndef EGL_KHR_lock_surface2 +#define EGL_KHR_lock_surface2 1 +#define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110 +#endif /* EGL_KHR_lock_surface2 */ -#ifndef EGL_KHR_gl_renderbuffer_image -#define EGL_KHR_gl_renderbuffer_image 1 -#define EGL_GL_RENDERBUFFER_KHR 0x30B9 /* eglCreateImageKHR target */ +#ifndef EGL_KHR_lock_surface3 +#define EGL_KHR_lock_surface3 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACE64KHRPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurface64KHR (EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLAttribKHR *value); #endif +#endif /* EGL_KHR_lock_surface3 */ + +#ifndef EGL_KHR_platform_android +#define EGL_KHR_platform_android 1 +#define EGL_PLATFORM_ANDROID_KHR 0x3141 +#endif /* EGL_KHR_platform_android */ + +#ifndef EGL_KHR_platform_gbm +#define EGL_KHR_platform_gbm 1 +#define EGL_PLATFORM_GBM_KHR 0x31D7 +#endif /* EGL_KHR_platform_gbm */ + +#ifndef EGL_KHR_platform_wayland +#define EGL_KHR_platform_wayland 1 +#define EGL_PLATFORM_WAYLAND_KHR 0x31D8 +#endif /* EGL_KHR_platform_wayland */ + +#ifndef EGL_KHR_platform_x11 +#define EGL_KHR_platform_x11 1 +#define EGL_PLATFORM_X11_KHR 0x31D5 +#define EGL_PLATFORM_X11_SCREEN_KHR 0x31D6 +#endif /* EGL_KHR_platform_x11 */ -#if KHRONOS_SUPPORT_INT64 /* EGLTimeKHR requires 64-bit uint support */ #ifndef EGL_KHR_reusable_sync #define EGL_KHR_reusable_sync 1 - -typedef void* EGLSyncKHR; typedef khronos_utime_nanoseconds_t EGLTimeKHR; - -#define EGL_SYNC_STATUS_KHR 0x30F1 -#define EGL_SIGNALED_KHR 0x30F2 -#define EGL_UNSIGNALED_KHR 0x30F3 -#define EGL_TIMEOUT_EXPIRED_KHR 0x30F5 -#define EGL_CONDITION_SATISFIED_KHR 0x30F6 -#define EGL_SYNC_TYPE_KHR 0x30F7 -#define EGL_SYNC_REUSABLE_KHR 0x30FA -#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001 /* eglClientWaitSyncKHR bitfield */ -#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull -#define EGL_NO_SYNC_KHR ((EGLSyncKHR)0) -#ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR(EGLDisplay dpy, EGLenum type, const EGLint *attrib_list); -EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR(EGLDisplay dpy, EGLSyncKHR sync); -EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout); -EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode); -EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR(EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value); -#endif /* EGL_EGLEXT_PROTOTYPES */ +#ifdef KHRONOS_SUPPORT_INT64 +#define EGL_SYNC_STATUS_KHR 0x30F1 +#define EGL_SIGNALED_KHR 0x30F2 +#define EGL_UNSIGNALED_KHR 0x30F3 +#define EGL_TIMEOUT_EXPIRED_KHR 0x30F5 +#define EGL_CONDITION_SATISFIED_KHR 0x30F6 +#define EGL_SYNC_TYPE_KHR 0x30F7 +#define EGL_SYNC_REUSABLE_KHR 0x30FA +#define EGL_SYNC_FLUSH_COMMANDS_BIT_KHR 0x0001 +#define EGL_FOREVER_KHR 0xFFFFFFFFFFFFFFFFull +#define EGL_NO_SYNC_KHR ((EGLSyncKHR)0) typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESYNCKHRPROC) (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list); typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync); typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout); typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode); typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateSyncKHR (EGLDisplay dpy, EGLenum type, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncKHR (EGLDisplay dpy, EGLSyncKHR sync); +EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, EGLTimeKHR timeout); +EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLenum mode); +EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, EGLint *value); +#endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_KHR_reusable_sync */ + +#ifndef EGL_KHR_stream +#define EGL_KHR_stream 1 +typedef void *EGLStreamKHR; +typedef khronos_uint64_t EGLuint64KHR; +#ifdef KHRONOS_SUPPORT_INT64 +#define EGL_NO_STREAM_KHR ((EGLStreamKHR)0) +#define EGL_CONSUMER_LATENCY_USEC_KHR 0x3210 +#define EGL_PRODUCER_FRAME_KHR 0x3212 +#define EGL_CONSUMER_FRAME_KHR 0x3213 +#define EGL_STREAM_STATE_KHR 0x3214 +#define EGL_STREAM_STATE_CREATED_KHR 0x3215 +#define EGL_STREAM_STATE_CONNECTING_KHR 0x3216 +#define EGL_STREAM_STATE_EMPTY_KHR 0x3217 +#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218 +#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219 +#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A +#define EGL_BAD_STREAM_KHR 0x321B +#define EGL_BAD_STATE_KHR 0x321C +typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMU64KHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamKHR (EGLDisplay dpy, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroyStreamKHR (EGLDisplay dpy, EGLStreamKHR stream); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamAttribKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint *value); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamu64KHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLuint64KHR *value); +#endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_KHR_stream */ + +#ifndef EGL_KHR_stream_consumer_gltexture +#define EGL_KHR_stream_consumer_gltexture 1 +#ifdef EGL_KHR_stream +#define EGL_CONSUMER_ACQUIRE_TIMEOUT_USEC_KHR 0x321E +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERGLTEXTUREEXTERNALKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERACQUIREKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMCONSUMERRELEASEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerGLTextureExternalKHR (EGLDisplay dpy, EGLStreamKHR stream); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerAcquireKHR (EGLDisplay dpy, EGLStreamKHR stream); +EGLAPI EGLBoolean EGLAPIENTRY eglStreamConsumerReleaseKHR (EGLDisplay dpy, EGLStreamKHR stream); +#endif +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_consumer_gltexture */ + +#ifndef EGL_KHR_stream_cross_process_fd +#define EGL_KHR_stream_cross_process_fd 1 +typedef int EGLNativeFileDescriptorKHR; +#ifdef EGL_KHR_stream +#define EGL_NO_FILE_DESCRIPTOR_KHR ((EGLNativeFileDescriptorKHR)(-1)) +typedef EGLNativeFileDescriptorKHR (EGLAPIENTRYP PFNEGLGETSTREAMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); +typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMFROMFILEDESCRIPTORKHRPROC) (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLNativeFileDescriptorKHR EGLAPIENTRY eglGetStreamFileDescriptorKHR (EGLDisplay dpy, EGLStreamKHR stream); +EGLAPI EGLStreamKHR EGLAPIENTRY eglCreateStreamFromFileDescriptorKHR (EGLDisplay dpy, EGLNativeFileDescriptorKHR file_descriptor); +#endif +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_cross_process_fd */ + +#ifndef EGL_KHR_stream_fifo +#define EGL_KHR_stream_fifo 1 +#ifdef EGL_KHR_stream +#define EGL_STREAM_FIFO_LENGTH_KHR 0x31FC +#define EGL_STREAM_TIME_NOW_KHR 0x31FD +#define EGL_STREAM_TIME_CONSUMER_KHR 0x31FE +#define EGL_STREAM_TIME_PRODUCER_KHR 0x31FF +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSTREAMTIMEKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryStreamTimeKHR (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLTimeKHR *value); +#endif +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_fifo */ + +#ifndef EGL_KHR_stream_producer_aldatalocator +#define EGL_KHR_stream_producer_aldatalocator 1 +#ifdef EGL_KHR_stream +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_producer_aldatalocator */ + +#ifndef EGL_KHR_stream_producer_eglsurface +#define EGL_KHR_stream_producer_eglsurface 1 +#ifdef EGL_KHR_stream +#define EGL_STREAM_BIT_KHR 0x0800 +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATESTREAMPRODUCERSURFACEKHRPROC) (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSurface EGLAPIENTRY eglCreateStreamProducerSurfaceKHR (EGLDisplay dpy, EGLConfig config, EGLStreamKHR stream, const EGLint *attrib_list); #endif -#endif +#endif /* EGL_KHR_stream */ +#endif /* EGL_KHR_stream_producer_eglsurface */ -#ifndef EGL_KHR_image_base -#define EGL_KHR_image_base 1 -/* Most interfaces defined by EGL_KHR_image_pixmap above */ -#define EGL_IMAGE_PRESERVED_KHR 0x30D2 /* eglCreateImageKHR attribute */ -#endif +#ifndef EGL_KHR_surfaceless_context +#define EGL_KHR_surfaceless_context 1 +#endif /* EGL_KHR_surfaceless_context */ -#ifndef EGL_KHR_image_pixmap -#define EGL_KHR_image_pixmap 1 -/* Interfaces defined by EGL_KHR_image above */ -#endif +#ifndef EGL_KHR_vg_parent_image +#define EGL_KHR_vg_parent_image 1 +#define EGL_VG_PARENT_IMAGE_KHR 0x30BA +#endif /* EGL_KHR_vg_parent_image */ -#ifndef EGL_IMG_context_priority -#define EGL_IMG_context_priority 1 -#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100 -#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101 -#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102 -#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103 +#ifndef EGL_KHR_wait_sync +#define EGL_KHR_wait_sync 1 +typedef EGLint (EGLAPIENTRYP PFNEGLWAITSYNCKHRPROC) (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLint EGLAPIENTRY eglWaitSyncKHR (EGLDisplay dpy, EGLSyncKHR sync, EGLint flags); #endif +#endif /* EGL_KHR_wait_sync */ -#ifndef EGL_KHR_lock_surface2 -#define EGL_KHR_lock_surface2 1 -#define EGL_BITMAP_PIXEL_SIZE_KHR 0x3110 +#ifndef EGL_ANDROID_blob_cache +#define EGL_ANDROID_blob_cache 1 +typedef khronos_ssize_t EGLsizeiANDROID; +typedef void (*EGLSetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, const void *value, EGLsizeiANDROID valueSize); +typedef EGLsizeiANDROID (*EGLGetBlobFuncANDROID) (const void *key, EGLsizeiANDROID keySize, void *value, EGLsizeiANDROID valueSize); +typedef void (EGLAPIENTRYP PFNEGLSETBLOBCACHEFUNCSANDROIDPROC) (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID (EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get); +#endif +#endif /* EGL_ANDROID_blob_cache */ + +#ifndef EGL_ANDROID_framebuffer_target +#define EGL_ANDROID_framebuffer_target 1 +#define EGL_FRAMEBUFFER_TARGET_ANDROID 0x3147 +#endif /* EGL_ANDROID_framebuffer_target */ + +#ifndef EGL_ANDROID_image_native_buffer +#define EGL_ANDROID_image_native_buffer 1 +#define EGL_NATIVE_BUFFER_ANDROID 0x3140 +#endif /* EGL_ANDROID_image_native_buffer */ + +#ifndef EGL_ANDROID_native_fence_sync +#define EGL_ANDROID_native_fence_sync 1 +#define EGL_SYNC_NATIVE_FENCE_ANDROID 0x3144 +#define EGL_SYNC_NATIVE_FENCE_FD_ANDROID 0x3145 +#define EGL_SYNC_NATIVE_FENCE_SIGNALED_ANDROID 0x3146 +#define EGL_NO_NATIVE_FENCE_FD_ANDROID -1 +typedef EGLint (EGLAPIENTRYP PFNEGLDUPNATIVEFENCEFDANDROIDPROC) (EGLDisplay dpy, EGLSyncKHR sync); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLint EGLAPIENTRY eglDupNativeFenceFDANDROID (EGLDisplay dpy, EGLSyncKHR sync); #endif +#endif /* EGL_ANDROID_native_fence_sync */ -#ifndef EGL_NV_coverage_sample -#define EGL_NV_coverage_sample 1 -#define EGL_COVERAGE_BUFFERS_NV 0x30E0 -#define EGL_COVERAGE_SAMPLES_NV 0x30E1 -#endif +#ifndef EGL_ANDROID_recordable +#define EGL_ANDROID_recordable 1 +#define EGL_RECORDABLE_ANDROID 0x3142 +#endif /* EGL_ANDROID_recordable */ -#ifndef EGL_NV_depth_nonlinear -#define EGL_NV_depth_nonlinear 1 -#define EGL_DEPTH_ENCODING_NV 0x30E2 -#define EGL_DEPTH_ENCODING_NONE_NV 0 -#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3 -#endif +#ifndef EGL_ANGLE_d3d_share_handle_client_buffer +#define EGL_ANGLE_d3d_share_handle_client_buffer 1 +#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200 +#endif /* EGL_ANGLE_d3d_share_handle_client_buffer */ -#if KHRONOS_SUPPORT_INT64 /* EGLTimeNV requires 64-bit uint support */ -#ifndef EGL_NV_sync -#define EGL_NV_sync 1 -#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6 -#define EGL_SYNC_STATUS_NV 0x30E7 -#define EGL_SIGNALED_NV 0x30E8 -#define EGL_UNSIGNALED_NV 0x30E9 -#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001 -#define EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull -#define EGL_ALREADY_SIGNALED_NV 0x30EA -#define EGL_TIMEOUT_EXPIRED_NV 0x30EB -#define EGL_CONDITION_SATISFIED_NV 0x30EC -#define EGL_SYNC_TYPE_NV 0x30ED -#define EGL_SYNC_CONDITION_NV 0x30EE -#define EGL_SYNC_FENCE_NV 0x30EF -#define EGL_NO_SYNC_NV ((EGLSyncNV)0) -typedef void* EGLSyncNV; -typedef khronos_utime_nanoseconds_t EGLTimeNV; +#ifndef EGL_ANGLE_window_fixed_size +#define EGL_ANGLE_window_fixed_size 1 +#define EGL_FIXED_SIZE_ANGLE 0x3201 +#endif /* EGL_ANGLE_window_fixed_size */ + +#ifndef EGL_ANGLE_query_surface_pointer +#define EGL_ANGLE_query_surface_pointer 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); #ifdef EGL_EGLEXT_PROTOTYPES -EGLSyncNV eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list); -EGLBoolean eglDestroySyncNV (EGLSyncNV sync); -EGLBoolean eglFenceNV (EGLSyncNV sync); -EGLint eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout); -EGLBoolean eglSignalSyncNV (EGLSyncNV sync, EGLenum mode); -EGLBoolean eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync); -typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value); -#endif +EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); #endif +#endif /* EGL_ANGLE_query_surface_pointer */ -#if KHRONOS_SUPPORT_INT64 /* Dependent on EGL_KHR_reusable_sync which requires 64-bit uint support */ -#ifndef EGL_KHR_fence_sync -#define EGL_KHR_fence_sync 1 -/* Reuses most tokens and entry points from EGL_KHR_reusable_sync */ -#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR 0x30F0 -#define EGL_SYNC_CONDITION_KHR 0x30F8 -#define EGL_SYNC_FENCE_KHR 0x30F9 -#endif +#ifndef EGL_ANGLE_software_display +#define EGL_ANGLE_software_display 1 +#define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1) +#endif /* EGL_ANGLE_software_display */ + +#ifndef EGL_ANGLE_direct3d_display +#define EGL_ANGLE_direct3d_display 1 +#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2) +#define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3) +#endif /* EGL_ANGLE_direct3d_display */ + +#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle +#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1 +#endif /* EGL_ANGLE_surface_d3d_texture_2d_share_handle */ + +#ifndef EGL_ANGLE_platform_angle +#define EGL_ANGLE_platform_angle 1 +#define EGL_PLATFORM_ANGLE_ANGLE 0x3201 +#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202 +#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3203 +#endif /* EGL_ANGLE_platform_angle */ + +#ifndef EGL_ANGLE_platform_angle_d3d +#define EGL_ANGLE_platform_angle_d3d 1 +#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3204 +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3205 +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE 0x3206 +#endif /* EGL_ANGLE_platform_angle_d3d */ + +#ifndef EGL_ANGLE_platform_angle_opengl +#define EGL_ANGLE_platform_angle_opengl 1 +#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3207 +#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x3208 +#endif /* EGL_ANGLE_platform_angle_opengl */ + +#ifndef EGL_ARM_pixmap_multisample_discard +#define EGL_ARM_pixmap_multisample_discard 1 +#define EGL_DISCARD_SAMPLES_ARM 0x3286 +#endif /* EGL_ARM_pixmap_multisample_discard */ + +#ifndef EGL_EXT_buffer_age +#define EGL_EXT_buffer_age 1 +#define EGL_BUFFER_AGE_EXT 0x313D +#endif /* EGL_EXT_buffer_age */ + +#ifndef EGL_EXT_client_extensions +#define EGL_EXT_client_extensions 1 +#endif /* EGL_EXT_client_extensions */ + +#ifndef EGL_EXT_create_context_robustness +#define EGL_EXT_create_context_robustness 1 +#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF +#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138 +#define EGL_NO_RESET_NOTIFICATION_EXT 0x31BE +#define EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF +#endif /* EGL_EXT_create_context_robustness */ + +#ifndef EGL_EXT_device_base +#define EGL_EXT_device_base 1 +typedef void *EGLDeviceEXT; +#define EGL_NO_DEVICE_EXT ((EGLDeviceEXT)(0)) +#define EGL_BAD_DEVICE_EXT 0x322B +#define EGL_DEVICE_EXT 0x322C +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICEATTRIBEXTPROC) (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value); +typedef const char *(EGLAPIENTRYP PFNEGLQUERYDEVICESTRINGEXTPROC) (EGLDeviceEXT device, EGLint name); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDEVICESEXTPROC) (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYDISPLAYATTRIBEXTPROC) (EGLDisplay dpy, EGLint attribute, EGLAttrib *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDeviceAttribEXT (EGLDeviceEXT device, EGLint attribute, EGLAttrib *value); +EGLAPI const char *EGLAPIENTRY eglQueryDeviceStringEXT (EGLDeviceEXT device, EGLint name); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDevicesEXT (EGLint max_devices, EGLDeviceEXT *devices, EGLint *num_devices); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryDisplayAttribEXT (EGLDisplay dpy, EGLint attribute, EGLAttrib *value); +#endif +#endif /* EGL_EXT_device_base */ + +#ifndef EGL_EXT_image_dma_buf_import +#define EGL_EXT_image_dma_buf_import 1 +#define EGL_LINUX_DMA_BUF_EXT 0x3270 +#define EGL_LINUX_DRM_FOURCC_EXT 0x3271 +#define EGL_DMA_BUF_PLANE0_FD_EXT 0x3272 +#define EGL_DMA_BUF_PLANE0_OFFSET_EXT 0x3273 +#define EGL_DMA_BUF_PLANE0_PITCH_EXT 0x3274 +#define EGL_DMA_BUF_PLANE1_FD_EXT 0x3275 +#define EGL_DMA_BUF_PLANE1_OFFSET_EXT 0x3276 +#define EGL_DMA_BUF_PLANE1_PITCH_EXT 0x3277 +#define EGL_DMA_BUF_PLANE2_FD_EXT 0x3278 +#define EGL_DMA_BUF_PLANE2_OFFSET_EXT 0x3279 +#define EGL_DMA_BUF_PLANE2_PITCH_EXT 0x327A +#define EGL_YUV_COLOR_SPACE_HINT_EXT 0x327B +#define EGL_SAMPLE_RANGE_HINT_EXT 0x327C +#define EGL_YUV_CHROMA_HORIZONTAL_SITING_HINT_EXT 0x327D +#define EGL_YUV_CHROMA_VERTICAL_SITING_HINT_EXT 0x327E +#define EGL_ITU_REC601_EXT 0x327F +#define EGL_ITU_REC709_EXT 0x3280 +#define EGL_ITU_REC2020_EXT 0x3281 +#define EGL_YUV_FULL_RANGE_EXT 0x3282 +#define EGL_YUV_NARROW_RANGE_EXT 0x3283 +#define EGL_YUV_CHROMA_SITING_0_EXT 0x3284 +#define EGL_YUV_CHROMA_SITING_0_5_EXT 0x3285 +#endif /* EGL_EXT_image_dma_buf_import */ + +#ifndef EGL_EXT_multiview_window +#define EGL_EXT_multiview_window 1 +#define EGL_MULTIVIEW_VIEW_COUNT_EXT 0x3134 +#endif /* EGL_EXT_multiview_window */ + +#ifndef EGL_EXT_platform_base +#define EGL_EXT_platform_base 1 +typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETPLATFORMDISPLAYEXTPROC) (EGLenum platform, void *native_display, const EGLint *attrib_list); +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list); +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPLATFORMPIXMAPSURFACEEXTPROC) (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT (EGLenum platform, void *native_display, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLint *attrib_list); +EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurfaceEXT (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLint *attrib_list); +#endif +#endif /* EGL_EXT_platform_base */ + +#ifndef EGL_EXT_platform_device +#define EGL_EXT_platform_device 1 +#define EGL_PLATFORM_DEVICE_EXT 0x313F +#endif /* EGL_EXT_platform_device */ + +#ifndef EGL_EXT_platform_wayland +#define EGL_EXT_platform_wayland 1 +#define EGL_PLATFORM_WAYLAND_EXT 0x31D8 +#endif /* EGL_EXT_platform_wayland */ + +#ifndef EGL_EXT_platform_x11 +#define EGL_EXT_platform_x11 1 +#define EGL_PLATFORM_X11_EXT 0x31D5 +#define EGL_PLATFORM_X11_SCREEN_EXT 0x31D6 +#endif /* EGL_EXT_platform_x11 */ + +#ifndef EGL_EXT_protected_surface +#define EGL_EXT_protected_surface 1 +#define EGL_PROTECTED_CONTENT_EXT 0x32C0 +#endif /* EGL_EXT_protected_surface */ + +#ifndef EGL_EXT_swap_buffers_with_damage +#define EGL_EXT_swap_buffers_with_damage 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC) (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT (EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects); #endif +#endif /* EGL_EXT_swap_buffers_with_damage */ #ifndef EGL_HI_clientpixmap #define EGL_HI_clientpixmap 1 - -/* Surface Attribute */ -#define EGL_CLIENT_PIXMAP_POINTER_HI 0x8F74 -/* - * Structure representing a client pixmap - * (pixmap's data is in client-space memory). - */ -struct EGLClientPixmapHI -{ - void* pData; - EGLint iWidth; - EGLint iHeight; - EGLint iStride; +struct EGLClientPixmapHI { + void *pData; + EGLint iWidth; + EGLint iHeight; + EGLint iStride; }; - +#define EGL_CLIENT_PIXMAP_POINTER_HI 0x8F74 +typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap); #ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI(EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLSurface (EGLAPIENTRYP PFNEGLCREATEPIXMAPSURFACEHIPROC) (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI* pixmap); -#endif /* EGL_HI_clientpixmap */ +EGLAPI EGLSurface EGLAPIENTRY eglCreatePixmapSurfaceHI (EGLDisplay dpy, EGLConfig config, struct EGLClientPixmapHI *pixmap); +#endif +#endif /* EGL_HI_clientpixmap */ #ifndef EGL_HI_colorformats #define EGL_HI_colorformats 1 -/* Config Attribute */ -#define EGL_COLOR_FORMAT_HI 0x8F70 -/* Color Formats */ -#define EGL_COLOR_RGB_HI 0x8F71 -#define EGL_COLOR_RGBA_HI 0x8F72 -#define EGL_COLOR_ARGB_HI 0x8F73 +#define EGL_COLOR_FORMAT_HI 0x8F70 +#define EGL_COLOR_RGB_HI 0x8F71 +#define EGL_COLOR_RGBA_HI 0x8F72 +#define EGL_COLOR_ARGB_HI 0x8F73 #endif /* EGL_HI_colorformats */ +#ifndef EGL_IMG_context_priority +#define EGL_IMG_context_priority 1 +#define EGL_CONTEXT_PRIORITY_LEVEL_IMG 0x3100 +#define EGL_CONTEXT_PRIORITY_HIGH_IMG 0x3101 +#define EGL_CONTEXT_PRIORITY_MEDIUM_IMG 0x3102 +#define EGL_CONTEXT_PRIORITY_LOW_IMG 0x3103 +#endif /* EGL_IMG_context_priority */ + #ifndef EGL_MESA_drm_image #define EGL_MESA_drm_image 1 -#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0 /* CreateDRMImageMESA attribute */ -#define EGL_DRM_BUFFER_USE_MESA 0x31D1 /* CreateDRMImageMESA attribute */ -#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2 /* EGL_IMAGE_FORMAT_MESA attribute value */ -#define EGL_DRM_BUFFER_MESA 0x31D3 /* eglCreateImageKHR target */ -#define EGL_DRM_BUFFER_STRIDE_MESA 0x31D4 -#define EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x00000001 /* EGL_DRM_BUFFER_USE_MESA bits */ -#define EGL_DRM_BUFFER_USE_SHARE_MESA 0x00000002 /* EGL_DRM_BUFFER_USE_MESA bits */ +#define EGL_DRM_BUFFER_FORMAT_MESA 0x31D0 +#define EGL_DRM_BUFFER_USE_MESA 0x31D1 +#define EGL_DRM_BUFFER_FORMAT_ARGB32_MESA 0x31D2 +#define EGL_DRM_BUFFER_MESA 0x31D3 +#define EGL_DRM_BUFFER_STRIDE_MESA 0x31D4 +#define EGL_DRM_BUFFER_USE_SCANOUT_MESA 0x00000001 +#define EGL_DRM_BUFFER_USE_SHARE_MESA 0x00000002 +typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride); #ifdef EGL_EGLEXT_PROTOTYPES EGLAPI EGLImageKHR EGLAPIENTRY eglCreateDRMImageMESA (EGLDisplay dpy, const EGLint *attrib_list); EGLAPI EGLBoolean EGLAPIENTRY eglExportDRMImageMESA (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLImageKHR (EGLAPIENTRYP PFNEGLCREATEDRMIMAGEMESAPROC) (EGLDisplay dpy, const EGLint *attrib_list); -typedef EGLBoolean (EGLAPIENTRYP PFNEGLEXPORTDRMIMAGEMESAPROC) (EGLDisplay dpy, EGLImageKHR image, EGLint *name, EGLint *handle, EGLint *stride); #endif +#endif /* EGL_MESA_drm_image */ -#ifndef EGL_NV_post_sub_buffer -#define EGL_NV_post_sub_buffer 1 -#define EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE +#ifndef EGL_MESA_platform_gbm +#define EGL_MESA_platform_gbm 1 +#define EGL_PLATFORM_GBM_MESA 0x31D7 +#endif /* EGL_MESA_platform_gbm */ + +#ifndef EGL_NOK_swap_region +#define EGL_NOK_swap_region 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); #ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height); +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegionNOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); #endif +#endif /* EGL_NOK_swap_region */ -#ifndef EGL_ANGLE_query_surface_pointer -#define EGL_ANGLE_query_surface_pointer 1 +#ifndef EGL_NOK_swap_region2 +#define EGL_NOK_swap_region2 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGION2NOKPROC) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); #ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLBoolean eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); -#endif -typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYSURFACEPOINTERANGLEPROC) (EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value); +EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersRegion2NOK (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint *rects); #endif +#endif /* EGL_NOK_swap_region2 */ -#ifndef EGL_ANGLE_software_display -#define EGL_ANGLE_software_display 1 -#define EGL_SOFTWARE_DISPLAY_ANGLE ((EGLNativeDisplayType)-1) -#endif +#ifndef EGL_NOK_texture_from_pixmap +#define EGL_NOK_texture_from_pixmap 1 +#define EGL_Y_INVERTED_NOK 0x307F +#endif /* EGL_NOK_texture_from_pixmap */ -#ifndef EGL_ANGLE_direct3d_display -#define EGL_ANGLE_direct3d_display 1 -#define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ((EGLNativeDisplayType)-2) -#define EGL_D3D11_ONLY_DISPLAY_ANGLE ((EGLNativeDisplayType)-3) -#endif +#ifndef EGL_NV_3dvision_surface +#define EGL_NV_3dvision_surface 1 +#define EGL_AUTO_STEREO_NV 0x3136 +#endif /* EGL_NV_3dvision_surface */ -#ifndef EGL_ANGLE_surface_d3d_texture_2d_share_handle -#define EGL_ANGLE_surface_d3d_texture_2d_share_handle 1 -#define EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE 0x3200 -#endif +#ifndef EGL_NV_coverage_sample +#define EGL_NV_coverage_sample 1 +#define EGL_COVERAGE_BUFFERS_NV 0x30E0 +#define EGL_COVERAGE_SAMPLES_NV 0x30E1 +#endif /* EGL_NV_coverage_sample */ #ifndef EGL_NV_coverage_sample_resolve #define EGL_NV_coverage_sample_resolve 1 -#define EGL_COVERAGE_SAMPLE_RESOLVE_NV 0x3131 -#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132 -#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133 +#define EGL_COVERAGE_SAMPLE_RESOLVE_NV 0x3131 +#define EGL_COVERAGE_SAMPLE_RESOLVE_DEFAULT_NV 0x3132 +#define EGL_COVERAGE_SAMPLE_RESOLVE_NONE_NV 0x3133 +#endif /* EGL_NV_coverage_sample_resolve */ + +#ifndef EGL_NV_depth_nonlinear +#define EGL_NV_depth_nonlinear 1 +#define EGL_DEPTH_ENCODING_NV 0x30E2 +#define EGL_DEPTH_ENCODING_NONE_NV 0 +#define EGL_DEPTH_ENCODING_NONLINEAR_NV 0x30E3 +#endif /* EGL_NV_depth_nonlinear */ + +#ifndef EGL_NV_native_query +#define EGL_NV_native_query 1 +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEDISPLAYNVPROC) (EGLDisplay dpy, EGLNativeDisplayType *display_id); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEWINDOWNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYNATIVEPIXMAPNVPROC) (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeDisplayNV (EGLDisplay dpy, EGLNativeDisplayType *display_id); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativeWindowNV (EGLDisplay dpy, EGLSurface surf, EGLNativeWindowType *window); +EGLAPI EGLBoolean EGLAPIENTRY eglQueryNativePixmapNV (EGLDisplay dpy, EGLSurface surf, EGLNativePixmapType *pixmap); #endif +#endif /* EGL_NV_native_query */ -#if KHRONOS_SUPPORT_INT64 /* EGLTimeKHR requires 64-bit uint support */ -#ifndef EGL_NV_system_time -#define EGL_NV_system_time 1 +#ifndef EGL_NV_post_convert_rounding +#define EGL_NV_post_convert_rounding 1 +#endif /* EGL_NV_post_convert_rounding */ -typedef khronos_utime_nanoseconds_t EGLuint64NV; +#ifndef EGL_NV_post_sub_buffer +#define EGL_NV_post_sub_buffer 1 +#define EGL_POST_SUB_BUFFER_SUPPORTED_NV 0x30BE +typedef EGLBoolean (EGLAPIENTRYP PFNEGLPOSTSUBBUFFERNVPROC) (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLBoolean EGLAPIENTRY eglPostSubBufferNV (EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height); +#endif +#endif /* EGL_NV_post_sub_buffer */ +#ifndef EGL_NV_stream_sync +#define EGL_NV_stream_sync 1 +#define EGL_SYNC_NEW_FRAME_NV 0x321F +typedef EGLSyncKHR (EGLAPIENTRYP PFNEGLCREATESTREAMSYNCNVPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list); #ifdef EGL_EGLEXT_PROTOTYPES -EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV(void); -EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV(void); -#endif /* EGL_EGLEXT_PROTOTYPES */ -typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void); -typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void); +EGLAPI EGLSyncKHR EGLAPIENTRY eglCreateStreamSyncNV (EGLDisplay dpy, EGLStreamKHR stream, EGLenum type, const EGLint *attrib_list); #endif +#endif /* EGL_NV_stream_sync */ + +#ifndef EGL_NV_sync +#define EGL_NV_sync 1 +typedef void *EGLSyncNV; +typedef khronos_utime_nanoseconds_t EGLTimeNV; +#ifdef KHRONOS_SUPPORT_INT64 +#define EGL_SYNC_PRIOR_COMMANDS_COMPLETE_NV 0x30E6 +#define EGL_SYNC_STATUS_NV 0x30E7 +#define EGL_SIGNALED_NV 0x30E8 +#define EGL_UNSIGNALED_NV 0x30E9 +#define EGL_SYNC_FLUSH_COMMANDS_BIT_NV 0x0001 +#define EGL_FOREVER_NV 0xFFFFFFFFFFFFFFFFull +#define EGL_ALREADY_SIGNALED_NV 0x30EA +#define EGL_TIMEOUT_EXPIRED_NV 0x30EB +#define EGL_CONDITION_SATISFIED_NV 0x30EC +#define EGL_SYNC_TYPE_NV 0x30ED +#define EGL_SYNC_CONDITION_NV 0x30EE +#define EGL_SYNC_FENCE_NV 0x30EF +#define EGL_NO_SYNC_NV ((EGLSyncNV)0) +typedef EGLSyncNV (EGLAPIENTRYP PFNEGLCREATEFENCESYNCNVPROC) (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSYNCNVPROC) (EGLSyncNV sync); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLFENCENVPROC) (EGLSyncNV sync); +typedef EGLint (EGLAPIENTRYP PFNEGLCLIENTWAITSYNCNVPROC) (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLSIGNALSYNCNVPROC) (EGLSyncNV sync, EGLenum mode); +typedef EGLBoolean (EGLAPIENTRYP PFNEGLGETSYNCATTRIBNVPROC) (EGLSyncNV sync, EGLint attribute, EGLint *value); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLSyncNV EGLAPIENTRY eglCreateFenceSyncNV (EGLDisplay dpy, EGLenum condition, const EGLint *attrib_list); +EGLAPI EGLBoolean EGLAPIENTRY eglDestroySyncNV (EGLSyncNV sync); +EGLAPI EGLBoolean EGLAPIENTRY eglFenceNV (EGLSyncNV sync); +EGLAPI EGLint EGLAPIENTRY eglClientWaitSyncNV (EGLSyncNV sync, EGLint flags, EGLTimeNV timeout); +EGLAPI EGLBoolean EGLAPIENTRY eglSignalSyncNV (EGLSyncNV sync, EGLenum mode); +EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttribNV (EGLSyncNV sync, EGLint attribute, EGLint *value); #endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_NV_sync */ -#ifndef EGL_EXT_create_context_robustness -#define EGL_EXT_create_context_robustness 1 -#define EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT 0x30BF -#define EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT 0x3138 -#define EGL_NO_RESET_NOTIFICATION_EXT 0x31BE -#define EGL_LOSE_CONTEXT_ON_RESET_EXT 0x31BF +#ifndef EGL_NV_system_time +#define EGL_NV_system_time 1 +typedef khronos_utime_nanoseconds_t EGLuint64NV; +#ifdef KHRONOS_SUPPORT_INT64 +typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC) (void); +typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC) (void); +#ifdef EGL_EGLEXT_PROTOTYPES +EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV (void); +EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV (void); #endif +#endif /* KHRONOS_SUPPORT_INT64 */ +#endif /* EGL_NV_system_time */ #ifdef __cplusplus } diff --git a/src/3rdparty/angle/include/EGL/eglplatform.h b/src/3rdparty/angle/include/EGL/eglplatform.h index eb15ae569d..ea9f5778ee 100644 --- a/src/3rdparty/angle/include/EGL/eglplatform.h +++ b/src/3rdparty/angle/include/EGL/eglplatform.h @@ -2,7 +2,7 @@ #define __eglplatform_h_ /* -** Copyright (c) 2007-2009 The Khronos Group Inc. +** Copyright (c) 2007-2013 The Khronos Group Inc. ** ** Permission is hereby granted, free of charge, to any person obtaining a ** copy of this software and/or associated documentation files (the @@ -25,7 +25,7 @@ */ /* Platform-specific types and definitions for egl.h - * $Revision: 12306 $ on $Date: 2010-08-25 09:51:28 -0700 (Wed, 25 Aug 2010) $ + * $Revision: 23432 $ on $Date: 2013-10-09 00:57:24 -0700 (Wed, 09 Oct 2013) $ * * Adopters may modify khrplatform.h and this file to suit their platform. * You are encouraged to submit all modifications to the Khronos group so that @@ -67,11 +67,11 @@ * implementations. */ -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) /* Windows Runtime */ +#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) /* Windows Runtime */ struct IUnknown; -typedef int EGLNativeDisplayType; +typedef IUnknown *EGLNativeDisplayType; typedef void *EGLNativePixmapType; typedef IUnknown *EGLNativeWindowType; @@ -91,13 +91,17 @@ typedef int EGLNativeDisplayType; typedef void *EGLNativeWindowType; typedef void *EGLNativePixmapType; -#elif defined(WL_EGL_PLATFORM) +#elif defined(__ANDROID__) || defined(ANDROID) -typedef struct wl_display *EGLNativeDisplayType; -typedef struct wl_egl_pixmap *EGLNativePixmapType; -typedef struct wl_egl_window *EGLNativeWindowType; +#include -#elif defined(__unix__) && !defined(ANDROID) +struct egl_native_pixmap_t; + +typedef struct ANativeWindow* EGLNativeWindowType; +typedef struct egl_native_pixmap_t* EGLNativePixmapType; +typedef void* EGLNativeDisplayType; + +#elif defined(__unix__) /* X11 (tentative) */ #include @@ -107,14 +111,6 @@ typedef Display *EGLNativeDisplayType; typedef Pixmap EGLNativePixmapType; typedef Window EGLNativeWindowType; -#elif defined(ANDROID) - -struct egl_native_pixmap_t; - -typedef struct ANativeWindow* EGLNativeWindowType; -typedef struct egl_native_pixmap_t* EGLNativePixmapType; -typedef void* EGLNativeDisplayType; - #else #error "Platform not recognized" #endif diff --git a/src/3rdparty/angle/include/GLES2/gl2.h b/src/3rdparty/angle/include/GLES2/gl2.h index e1d3b87cc5..c2d8357268 100644 --- a/src/3rdparty/angle/include/GLES2/gl2.h +++ b/src/3rdparty/angle/include/GLES2/gl2.h @@ -1,7 +1,7 @@ #ifndef __gl2_h_ #define __gl2_h_ -/* $Revision: 10602 $ on $Date:: 2010-03-04 22:35:34 -0800 #$ */ +/* $Revision: 20555 $ on $Date:: 2013-02-12 14:32:47 -0800 #$ */ #include @@ -431,7 +431,6 @@ typedef khronos_ssize_t GLsizeiptr; #define GL_RGB5_A1 0x8057 #define GL_RGB565 0x8D62 #define GL_DEPTH_COMPONENT16 0x81A5 -#define GL_STENCIL_INDEX 0x1901 #define GL_STENCIL_INDEX8 0x8D48 #define GL_RENDERBUFFER_WIDTH 0x8D42 @@ -528,7 +527,7 @@ GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures); GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name); GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name); GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); -GL_APICALL int GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name); +GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name); GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params); GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params); GL_APICALL GLenum GL_APIENTRY glGetError (void); @@ -547,7 +546,7 @@ GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum p GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params); GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params); GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params); -GL_APICALL int GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name); +GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name); GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params); GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params); GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer); @@ -569,7 +568,7 @@ GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum GL_APICALL void GL_APIENTRY glSampleCoverage (GLclampf value, GLboolean invert); GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length); -GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar** string, const GLint* length); +GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length); GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask); diff --git a/src/3rdparty/angle/include/GLES2/gl2ext.h b/src/3rdparty/angle/include/GLES2/gl2ext.h index bad50f9ccb..d77fdbaebc 100644 --- a/src/3rdparty/angle/include/GLES2/gl2ext.h +++ b/src/3rdparty/angle/include/GLES2/gl2ext.h @@ -1,7 +1,7 @@ #ifndef __gl2ext_h_ #define __gl2ext_h_ -/* $Revision: 16482 $ on $Date:: 2012-01-04 13:44:55 -0500 #$ */ +/* $Revision: 20795 $ on $Date:: 2013-03-07 01:01:58 -0800 #$ */ #ifdef __cplusplus extern "C" { @@ -93,6 +93,25 @@ typedef void* GLeglImageOES; #define GL_DEPTH24_STENCIL8_OES 0x88F0 #endif +/* GL_OES_required_internalformat */ +#ifndef GL_OES_required_internalformat +#define GL_ALPHA8_OES 0x803C +#define GL_DEPTH_COMPONENT16_OES 0x81A5 +/* reuse GL_DEPTH_COMPONENT24_OES */ +/* reuse GL_DEPTH24_STENCIL8_OES */ +/* reuse GL_DEPTH_COMPONENT32_OES */ +#define GL_LUMINANCE4_ALPHA4_OES 0x8043 +#define GL_LUMINANCE8_ALPHA8_OES 0x8045 +#define GL_LUMINANCE8_OES 0x8040 +#define GL_RGBA4_OES 0x8056 +#define GL_RGB5_A1_OES 0x8057 +#define GL_RGB565_OES 0x8D62 +/* reuse GL_RGB8_OES */ +/* reuse GL_RGBA8_OES */ +/* reuse GL_RGB10_EXT */ +/* reuse GL_RGB10_A2_EXT */ +#endif + /* GL_OES_rgb8_rgba8 */ #ifndef GL_OES_rgb8_rgba8 #define GL_RGB8_OES 0x8051 @@ -114,6 +133,10 @@ typedef void* GLeglImageOES; #define GL_STENCIL_INDEX4_OES 0x8D47 #endif +#ifndef GL_OES_surfaceless_context +#define GL_FRAMEBUFFER_UNDEFINED_OES 0x8219 +#endif + /* GL_OES_texture_3D */ #ifndef GL_OES_texture_3D #define GL_TEXTURE_WRAP_R_OES 0x8072 @@ -155,6 +178,85 @@ typedef void* GLeglImageOES; #define GL_INT_10_10_10_2_OES 0x8DF7 #endif +/*------------------------------------------------------------------------* + * KHR extension tokens + *------------------------------------------------------------------------*/ + +#ifndef GL_KHR_debug +typedef void (GL_APIENTRYP GLDEBUGPROC)(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei length,const GLchar *message,GLvoid *userParam); +#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242 +#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243 +#define GL_DEBUG_CALLBACK_FUNCTION 0x8244 +#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245 +#define GL_DEBUG_SOURCE_API 0x8246 +#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247 +#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248 +#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249 +#define GL_DEBUG_SOURCE_APPLICATION 0x824A +#define GL_DEBUG_SOURCE_OTHER 0x824B +#define GL_DEBUG_TYPE_ERROR 0x824C +#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D +#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E +#define GL_DEBUG_TYPE_PORTABILITY 0x824F +#define GL_DEBUG_TYPE_PERFORMANCE 0x8250 +#define GL_DEBUG_TYPE_OTHER 0x8251 +#define GL_DEBUG_TYPE_MARKER 0x8268 +#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269 +#define GL_DEBUG_TYPE_POP_GROUP 0x826A +#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B +#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C +#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D +#define GL_BUFFER 0x82E0 +#define GL_SHADER 0x82E1 +#define GL_PROGRAM 0x82E2 +#define GL_QUERY 0x82E3 +/* PROGRAM_PIPELINE only in GL */ +#define GL_SAMPLER 0x82E6 +/* DISPLAY_LIST only in GL */ +#define GL_MAX_LABEL_LENGTH 0x82E8 +#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143 +#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144 +#define GL_DEBUG_LOGGED_MESSAGES 0x9145 +#define GL_DEBUG_SEVERITY_HIGH 0x9146 +#define GL_DEBUG_SEVERITY_MEDIUM 0x9147 +#define GL_DEBUG_SEVERITY_LOW 0x9148 +#define GL_DEBUG_OUTPUT 0x92E0 +#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002 +#define GL_STACK_OVERFLOW 0x0503 +#define GL_STACK_UNDERFLOW 0x0504 +#endif + +#ifndef GL_KHR_texture_compression_astc_ldr +#define GL_COMPRESSED_RGBA_ASTC_4x4_KHR 0x93B0 +#define GL_COMPRESSED_RGBA_ASTC_5x4_KHR 0x93B1 +#define GL_COMPRESSED_RGBA_ASTC_5x5_KHR 0x93B2 +#define GL_COMPRESSED_RGBA_ASTC_6x5_KHR 0x93B3 +#define GL_COMPRESSED_RGBA_ASTC_6x6_KHR 0x93B4 +#define GL_COMPRESSED_RGBA_ASTC_8x5_KHR 0x93B5 +#define GL_COMPRESSED_RGBA_ASTC_8x6_KHR 0x93B6 +#define GL_COMPRESSED_RGBA_ASTC_8x8_KHR 0x93B7 +#define GL_COMPRESSED_RGBA_ASTC_10x5_KHR 0x93B8 +#define GL_COMPRESSED_RGBA_ASTC_10x6_KHR 0x93B9 +#define GL_COMPRESSED_RGBA_ASTC_10x8_KHR 0x93BA +#define GL_COMPRESSED_RGBA_ASTC_10x10_KHR 0x93BB +#define GL_COMPRESSED_RGBA_ASTC_12x10_KHR 0x93BC +#define GL_COMPRESSED_RGBA_ASTC_12x12_KHR 0x93BD +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR 0x93D0 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR 0x93D1 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR 0x93D2 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR 0x93D3 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR 0x93D4 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR 0x93D5 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR 0x93D6 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR 0x93D7 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR 0x93D8 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR 0x93D9 +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR 0x93DA +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR 0x93DB +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR 0x93DC +#define GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR 0x93DD +#endif + /*------------------------------------------------------------------------* * AMD extension tokens *------------------------------------------------------------------------*/ @@ -192,6 +294,18 @@ typedef void* GLeglImageOES; * ANGLE extension tokens *------------------------------------------------------------------------*/ +/* GL_ANGLE_depth_texture */ +#ifndef GL_ANGLE_depth_texture +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_DEPTH_STENCIL_OES 0x84F9 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_UNSIGNED_INT 0x1405 +#define GL_UNSIGNED_INT_24_8_OES 0x84FA +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_DEPTH_COMPONENT32_OES 0x81A7 +#define GL_DEPTH24_STENCIL8_OES 0x88F0 +#endif + /* GL_ANGLE_framebuffer_blit */ #ifndef GL_ANGLE_framebuffer_blit #define GL_READ_FRAMEBUFFER_ANGLE 0x8CA8 @@ -207,53 +321,49 @@ typedef void* GLeglImageOES; #define GL_MAX_SAMPLES_ANGLE 0x8D57 #endif +/* GL_ANGLE_instanced_arrays */ +#ifndef GL_ANGLE_instanced_arrays +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE +#endif + /* GL_ANGLE_pack_reverse_row_order */ -#ifndef GL_ANGLE_pack_reverse_row_order +#ifndef GL_ANGLE_pack_reverse_row_order #define GL_PACK_REVERSE_ROW_ORDER_ANGLE 0x93A4 #endif +/* GL_ANGLE_program_binary */ +#ifndef GL_ANGLE_program_binary +#define GL_PROGRAM_BINARY_ANGLE 0x93A6 +#endif + /* GL_ANGLE_texture_compression_dxt3 */ -#ifndef GL_ANGLE_texture_compression_dxt3 +#ifndef GL_ANGLE_texture_compression_dxt3 #define GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE 0x83F2 #endif /* GL_ANGLE_texture_compression_dxt5 */ -#ifndef GL_ANGLE_texture_compression_dxt5 +#ifndef GL_ANGLE_texture_compression_dxt5 #define GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE 0x83F3 #endif -/* GL_ANGLE_translated_shader_source */ -#ifndef GL_ANGLE_translated_shader_source -#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0 -#endif - /* GL_ANGLE_texture_usage */ -#ifndef GL_ANGLE_texture_usage +#ifndef GL_ANGLE_texture_usage #define GL_TEXTURE_USAGE_ANGLE 0x93A2 #define GL_FRAMEBUFFER_ATTACHMENT_ANGLE 0x93A3 #endif -/* GL_ANGLE_instanced_arrays */ -#ifndef GL_ANGLE_instanced_arrays -#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE 0x88FE -#endif - -/* GL_ANGLE_program_binary */ -#ifndef GL_ANGLE_program_binary -#define GL_PROGRAM_BINARY_ANGLE 0x93A6 +/* GL_ANGLE_translated_shader_source */ +#ifndef GL_ANGLE_translated_shader_source +#define GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE 0x93A0 #endif /*------------------------------------------------------------------------* * APPLE extension tokens *------------------------------------------------------------------------*/ -/* GL_APPLE_rgb_422 */ -#ifndef GL_APPLE_rgb_422 -#define GL_RGB_422_APPLE 0x8A1F -#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA -#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB -#endif - +/* GL_APPLE_copy_texture_levels */ +/* No new tokens introduced by this extension. */ + /* GL_APPLE_framebuffer_multisample */ #ifndef GL_APPLE_framebuffer_multisample #define GL_RENDERBUFFER_SAMPLES_APPLE 0x8CAB @@ -265,6 +375,47 @@ typedef void* GLeglImageOES; #define GL_READ_FRAMEBUFFER_BINDING_APPLE 0x8CAA #endif +/* GL_APPLE_rgb_422 */ +#ifndef GL_APPLE_rgb_422 +#define GL_RGB_422_APPLE 0x8A1F +#define GL_UNSIGNED_SHORT_8_8_APPLE 0x85BA +#define GL_UNSIGNED_SHORT_8_8_REV_APPLE 0x85BB +#endif + +/* GL_APPLE_sync */ +#ifndef GL_APPLE_sync + +#ifndef __gl3_h_ +/* These types are defined with reference to + * in the Apple extension spec, but here we use the Khronos + * portable types in khrplatform.h, and assume those types + * are always defined. + * If any other extensions using these types are defined, + * the typedefs must move out of this block and be shared. + */ +typedef khronos_int64_t GLint64; +typedef khronos_uint64_t GLuint64; +typedef struct __GLsync *GLsync; +#endif + +#define GL_SYNC_OBJECT_APPLE 0x8A53 +#define GL_MAX_SERVER_WAIT_TIMEOUT_APPLE 0x9111 +#define GL_OBJECT_TYPE_APPLE 0x9112 +#define GL_SYNC_CONDITION_APPLE 0x9113 +#define GL_SYNC_STATUS_APPLE 0x9114 +#define GL_SYNC_FLAGS_APPLE 0x9115 +#define GL_SYNC_FENCE_APPLE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE 0x9117 +#define GL_UNSIGNALED_APPLE 0x9118 +#define GL_SIGNALED_APPLE 0x9119 +#define GL_ALREADY_SIGNALED_APPLE 0x911A +#define GL_TIMEOUT_EXPIRED_APPLE 0x911B +#define GL_CONDITION_SATISFIED_APPLE 0x911C +#define GL_WAIT_FAILED_APPLE 0x911D +#define GL_SYNC_FLUSH_COMMANDS_BIT_APPLE 0x00000001 +#define GL_TIMEOUT_IGNORED_APPLE 0xFFFFFFFFFFFFFFFFull +#endif + /* GL_APPLE_texture_format_BGRA8888 */ #ifndef GL_APPLE_texture_format_BGRA8888 #define GL_BGRA_EXT 0x80E1 @@ -279,6 +430,11 @@ typedef void* GLeglImageOES; * ARM extension tokens *------------------------------------------------------------------------*/ +/* GL_ARM_mali_program_binary */ +#ifndef GL_ARM_mali_program_binary +#define GL_MALI_PROGRAM_BINARY_ARM 0x8F61 +#endif + /* GL_ARM_mali_shader_binary */ #ifndef GL_ARM_mali_shader_binary #define GL_MALI_SHADER_BINARY_ARM 0x8F60 @@ -327,12 +483,32 @@ typedef void* GLeglImageOES; #define GL_STENCIL_EXT 0x1802 #endif +/* GL_EXT_map_buffer_range */ +#ifndef GL_EXT_map_buffer_range +#define GL_MAP_READ_BIT_EXT 0x0001 +#define GL_MAP_WRITE_BIT_EXT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT_EXT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT_EXT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT_EXT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT_EXT 0x0020 +#endif + /* GL_EXT_multisampled_render_to_texture */ #ifndef GL_EXT_multisampled_render_to_texture #define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT 0x8D6C -#define GL_RENDERBUFFER_SAMPLES_EXT 0x9133 -#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x9134 -#define GL_MAX_SAMPLES_EXT 0x9135 +/* reuse values from GL_EXT_framebuffer_multisample (desktop extension) */ +#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56 +#define GL_MAX_SAMPLES_EXT 0x8D57 +#endif + +/* GL_EXT_multiview_draw_buffers */ +#ifndef GL_EXT_multiview_draw_buffers +#define GL_COLOR_ATTACHMENT_EXT 0x90F0 +#define GL_MULTIVIEW_EXT 0x90F1 +#define GL_DRAW_BUFFER_EXT 0x0C01 +#define GL_READ_BUFFER_EXT 0x0C02 +#define GL_MAX_MULTIVIEW_BUFFERS_EXT 0x90F2 #endif /* GL_EXT_multi_draw_arrays */ @@ -376,6 +552,11 @@ typedef void* GLeglImageOES; #define GL_PROGRAM_PIPELINE_BINDING_EXT 0x825A #endif +/* GL_EXT_shader_framebuffer_fetch */ +#ifndef GL_EXT_shader_framebuffer_fetch +#define GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT 0x8A52 +#endif + /* GL_EXT_shader_texture_lod */ /* No new tokens introduced by this extension. */ @@ -384,6 +565,7 @@ typedef void* GLeglImageOES; #define GL_TEXTURE_COMPARE_MODE_EXT 0x884C #define GL_TEXTURE_COMPARE_FUNC_EXT 0x884D #define GL_COMPARE_REF_TO_TEXTURE_EXT 0x884E +#define GL_SAMPLER_2D_SHADOW_EXT 0x8B62 #endif /* GL_EXT_sRGB */ @@ -431,13 +613,19 @@ typedef void* GLeglImageOES; #define GL_LUMINANCE32F_EXT 0x8818 #define GL_LUMINANCE_ALPHA32F_EXT 0x8819 /* reuse GL_RGBA16F_EXT */ -#define GL_RGB16F_EXT 0x881B +/* reuse GL_RGB16F_EXT */ #define GL_ALPHA16F_EXT 0x881C #define GL_LUMINANCE16F_EXT 0x881E #define GL_LUMINANCE_ALPHA16F_EXT 0x881F #define GL_RGB10_A2_EXT 0x8059 #define GL_RGB10_EXT 0x8052 #define GL_BGRA8_EXT 0x93A1 +#define GL_R8_EXT 0x8229 +#define GL_RG8_EXT 0x822B +#define GL_R32F_EXT 0x822E +#define GL_RG32F_EXT 0x8230 +#define GL_R16F_EXT 0x822D +#define GL_RG16F_EXT 0x822F #endif /* GL_EXT_texture_type_2_10_10_10_REV */ @@ -447,9 +635,9 @@ typedef void* GLeglImageOES; /* GL_EXT_unpack_subimage */ #ifndef GL_EXT_unpack_subimage -#define GL_UNPACK_ROW_LENGTH 0x0CF2 -#define GL_UNPACK_SKIP_ROWS 0x0CF3 -#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_UNPACK_ROW_LENGTH_EXT 0x0CF2 +#define GL_UNPACK_SKIP_ROWS_EXT 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS_EXT 0x0CF4 #endif /*------------------------------------------------------------------------* @@ -461,6 +649,15 @@ typedef void* GLeglImageOES; #define GL_SHADER_BINARY_DMP 0x9250 #endif +/*------------------------------------------------------------------------* + * FJ extension tokens + *------------------------------------------------------------------------*/ + +/* GL_FJ_shader_binary_GCCSO */ +#ifndef GL_FJ_shader_binary_GCCSO +#define GL_GCCSO_SHADER_BINARY_F 0x9260 +#endif + /*------------------------------------------------------------------------* * IMG extension tokens *------------------------------------------------------------------------*/ @@ -489,6 +686,12 @@ typedef void* GLeglImageOES; #define GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG 0x8C03 #endif +/* GL_IMG_texture_compression_pvrtc2 */ +#ifndef GL_IMG_texture_compression_pvrtc2 +#define GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG 0x9137 +#define GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG 0x9138 +#endif + /* GL_IMG_multisampled_render_to_texture */ #ifndef GL_IMG_multisampled_render_to_texture #define GL_RENDERBUFFER_SAMPLES_IMG 0x9133 @@ -594,6 +797,9 @@ typedef void* GLeglImageOES; #define GL_MAX_COLOR_ATTACHMENTS_EXT 0x8CDF #endif +/* GL_NV_draw_instanced */ +/* No new tokens introduced by this extension. */ + /* GL_NV_fbo_color_attachments */ #ifndef GL_NV_fbo_color_attachments #define GL_MAX_COLOR_ATTACHMENTS_NV 0x8CDF @@ -607,6 +813,29 @@ typedef void* GLeglImageOES; #define GL_FENCE_CONDITION_NV 0x84F4 #endif +/* GL_NV_framebuffer_blit */ +#ifndef GL_NV_framebuffer_blit +#define GL_READ_FRAMEBUFFER_NV 0x8CA8 +#define GL_DRAW_FRAMEBUFFER_NV 0x8CA9 +#define GL_DRAW_FRAMEBUFFER_BINDING_NV 0x8CA6 +#define GL_READ_FRAMEBUFFER_BINDING_NV 0x8CAA +#endif + +/* GL_NV_framebuffer_multisample */ +#ifndef GL_NV_framebuffer_multisample +#define GL_RENDERBUFFER_SAMPLES_NV 0x8CAB +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_NV 0x8D56 +#define GL_MAX_SAMPLES_NV 0x8D57 +#endif + +/* GL_NV_generate_mipmap_sRGB */ +/* No new tokens introduced by this extension. */ + +/* GL_NV_instanced_arrays */ +#ifndef GL_NV_instanced_arrays +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR_NV 0x88FE +#endif + /* GL_NV_read_buffer */ #ifndef GL_NV_read_buffer #define GL_READ_BUFFER_NV 0x0C02 @@ -624,6 +853,36 @@ typedef void* GLeglImageOES; /* GL_NV_read_stencil */ /* No new tokens introduced by this extension. */ +/* GL_NV_shadow_samplers_array */ +#ifndef GL_NV_shadow_samplers_array +#define GL_SAMPLER_2D_ARRAY_SHADOW_NV 0x8DC4 +#endif + +/* GL_NV_shadow_samplers_cube */ +#ifndef GL_NV_shadow_samplers_cube +#define GL_SAMPLER_CUBE_SHADOW_NV 0x8DC5 +#endif + +/* GL_NV_sRGB_formats */ +#ifndef GL_NV_sRGB_formats +#define GL_SLUMINANCE_NV 0x8C46 +#define GL_SLUMINANCE_ALPHA_NV 0x8C44 +#define GL_SRGB8_NV 0x8C41 +#define GL_SLUMINANCE8_NV 0x8C47 +#define GL_SLUMINANCE8_ALPHA8_NV 0x8C45 +#define GL_COMPRESSED_SRGB_S3TC_DXT1_NV 0x8C4C +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV 0x8C4D +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV 0x8C4E +#define GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV 0x8C4F +#define GL_ETC1_SRGB8_NV 0x88EE +#endif + +/* GL_NV_texture_border_clamp */ +#ifndef GL_NV_texture_border_clamp +#define GL_TEXTURE_BORDER_COLOR_NV 0x1004 +#define GL_CLAMP_TO_BORDER_NV 0x812D +#endif + /* GL_NV_texture_compression_s3tc_update */ /* No new tokens introduced by this extension. */ @@ -641,6 +900,14 @@ typedef void* GLeglImageOES; #define GL_ALPHA_TEST_REF_QCOM 0x0BC2 #endif +/* GL_QCOM_binning_control */ +#ifndef GL_QCOM_binning_control +#define GL_BINNING_CONTROL_HINT_QCOM 0x8FB0 +#define GL_CPU_OPTIMIZED_QCOM 0x8FB1 +#define GL_GPU_OPTIMIZED_QCOM 0x8FB2 +#define GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM 0x8FB3 +#endif + /* GL_QCOM_driver_control */ /* No new tokens introduced by this extension. */ @@ -811,6 +1078,11 @@ typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum #define GL_OES_packed_depth_stencil 1 #endif +/* GL_OES_required_internalformat */ +#ifndef GL_OES_required_internalformat +#define GL_OES_required_internalformat 1 +#endif + /* GL_OES_rgb8_rgba8 */ #ifndef GL_OES_rgb8_rgba8 #define GL_OES_rgb8_rgba8 1 @@ -831,6 +1103,10 @@ typedef void (GL_APIENTRYP PFNGLGETBUFFERPOINTERVOESPROC) (GLenum target, GLenum #define GL_OES_stencil4 1 #endif +#ifndef GL_OES_surfaceless_context +#define GL_OES_surfaceless_context 1 +#endif + /* GL_OES_texture_3D */ #ifndef GL_OES_texture_3D #define GL_OES_texture_3D 1 @@ -900,6 +1176,43 @@ typedef GLboolean (GL_APIENTRYP PFNGLISVERTEXARRAYOESPROC) (GLuint array); #define GL_OES_vertex_type_10_10_10_2 1 #endif +/*------------------------------------------------------------------------* + * KHR extension functions + *------------------------------------------------------------------------*/ + +#ifndef GL_KHR_debug +#define GL_KHR_debug 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDebugMessageControl (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +GL_APICALL void GL_APIENTRY glDebugMessageInsert (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +GL_APICALL void GL_APIENTRY glDebugMessageCallback (GLDEBUGPROC callback, const void *userParam); +GL_APICALL GLuint GL_APIENTRY glGetDebugMessageLog (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +GL_APICALL void GL_APIENTRY glPushDebugGroup (GLenum source, GLuint id, GLsizei length, const GLchar *message); +GL_APICALL void GL_APIENTRY glPopDebugGroup (void); +GL_APICALL void GL_APIENTRY glObjectLabel (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); +GL_APICALL void GL_APIENTRY glGetObjectLabel (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); +GL_APICALL void GL_APIENTRY glObjectPtrLabel (const void *ptr, GLsizei length, const GLchar *label); +GL_APICALL void GL_APIENTRY glGetObjectPtrLabel (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); +GL_APICALL void GL_APIENTRY glGetPointerv (GLenum pname, void **params); +#endif +typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled); +typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf); +typedef void (GL_APIENTRYP PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam); +typedef GLuint (GL_APIENTRYP PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufsize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog); +typedef void (GL_APIENTRYP PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message); +typedef void (GL_APIENTRYP PFNGLPOPDEBUGGROUPPROC) (void); +typedef void (GL_APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label); +typedef void (GL_APIENTRYP PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label); +typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label); +typedef void (GL_APIENTRYP PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label); +typedef void (GL_APIENTRYP PFNGLGETPOINTERVPROC) (GLenum pname, void **params); +#endif + +#ifndef GL_KHR_texture_compression_astc_ldr +#define GL_KHR_texture_compression_astc_ldr 1 +#endif + + /*------------------------------------------------------------------------* * AMD extension functions *------------------------------------------------------------------------*/ @@ -952,6 +1265,11 @@ typedef void (GL_APIENTRYP PFNGLGETPERFMONITORCOUNTERDATAAMDPROC) (GLuint monito * ANGLE extension functions *------------------------------------------------------------------------*/ +/* GL_ANGLE_depth_texture */ +#ifndef GL_ANGLE_depth_texture +#define GL_ANGLE_depth_texture 1 +#endif + /* GL_ANGLE_framebuffer_blit */ #ifndef GL_ANGLE_framebuffer_blit #define GL_ANGLE_framebuffer_blit 1 @@ -970,55 +1288,62 @@ GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleANGLE (GLenum target typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEANGLEPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); #endif +#ifndef GL_ANGLE_instanced_arrays +#define GL_ANGLE_instanced_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE (GLuint index, GLuint divisor); +#endif +typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount); +typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor); +#endif + /* GL_ANGLE_pack_reverse_row_order */ -#ifndef GL_ANGLE_pack_reverse_row_order +#ifndef GL_ANGLE_pack_reverse_row_order #define GL_ANGLE_pack_reverse_row_order 1 #endif +/* GL_ANGLE_program_binary */ +#ifndef GL_ANGLE_program_binary +#define GL_ANGLE_program_binary 1 +#endif + /* GL_ANGLE_texture_compression_dxt3 */ -#ifndef GL_ANGLE_texture_compression_dxt3 +#ifndef GL_ANGLE_texture_compression_dxt3 #define GL_ANGLE_texture_compression_dxt3 1 #endif /* GL_ANGLE_texture_compression_dxt5 */ -#ifndef GL_ANGLE_texture_compression_dxt5 +#ifndef GL_ANGLE_texture_compression_dxt5 #define GL_ANGLE_texture_compression_dxt5 1 #endif -/* GL_ANGLE_translated_shader_source */ -#ifndef GL_ANGLE_translated_shader_source -#define GL_ANGLE_translated_shader_source 1 -#ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source); -#endif -typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source); -#endif - /* GL_ANGLE_texture_usage */ -#ifndef GL_ANGLE_texture_usage +#ifndef GL_ANGLE_texture_usage #define GL_ANGLE_texture_usage 1 #endif -/* GL_ANGLE_instanced_arrays */ -#ifndef GL_ANGLE_instanced_arrays -#define GL_ANGLE_instanced_arrays 1 +#ifndef GL_ANGLE_translated_shader_source +#define GL_ANGLE_translated_shader_source 1 #ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glVertexAttribDivisorANGLE(GLuint index, GLuint divisor); -GL_APICALL void GL_APIENTRY glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount); -GL_APICALL void GL_APIENTRY glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); +GL_APICALL void GL_APIENTRY glGetTranslatedShaderSourceANGLE (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source); #endif -typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORANGLEPROC) (GLuint index, GLuint divisor); -typedef void (GL_APIENTRYP PFNGLDRAWARRAYSINSTANCEDANGLEPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); -typedef void (GL_APIENTRYP PFNGLDRAWELEMENTSINSTANCEDANGLEPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); +typedef void (GL_APIENTRYP PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC) (GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source); #endif /*------------------------------------------------------------------------* * APPLE extension functions *------------------------------------------------------------------------*/ -/* GL_APPLE_rgb_422 */ -#ifndef GL_APPLE_rgb_422 -#define GL_APPLE_rgb_422 1 +/* GL_APPLE_copy_texture_levels */ +#ifndef GL_APPLE_copy_texture_levels +#define GL_APPLE_copy_texture_levels 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glCopyTextureLevelsAPPLE (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount); +#endif +typedef void (GL_APIENTRYP PFNGLCOPYTEXTURELEVELSAPPLEPROC) (GLuint destinationTexture, GLuint sourceTexture, GLint sourceBaseLevel, GLsizei sourceLevelCount); #endif /* GL_APPLE_framebuffer_multisample */ @@ -1032,6 +1357,32 @@ typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEAPPLEPROC) (GLenum typedef void (GL_APIENTRYP PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void); #endif +/* GL_APPLE_rgb_422 */ +#ifndef GL_APPLE_rgb_422 +#define GL_APPLE_rgb_422 1 +#endif + +/* GL_APPLE_sync */ +#ifndef GL_APPLE_sync +#define GL_APPLE_sync 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL GLsync GL_APIENTRY glFenceSyncAPPLE (GLenum condition, GLbitfield flags); +GL_APICALL GLboolean GL_APIENTRY glIsSyncAPPLE (GLsync sync); +GL_APICALL void GL_APIENTRY glDeleteSyncAPPLE (GLsync sync); +GL_APICALL GLenum GL_APIENTRY glClientWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout); +GL_APICALL void GL_APIENTRY glWaitSyncAPPLE (GLsync sync, GLbitfield flags, GLuint64 timeout); +GL_APICALL void GL_APIENTRY glGetInteger64vAPPLE (GLenum pname, GLint64 *params); +GL_APICALL void GL_APIENTRY glGetSyncivAPPLE (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +#endif +typedef GLsync (GL_APIENTRYP PFNGLFENCESYNCAPPLEPROC) (GLenum condition, GLbitfield flags); +typedef GLboolean (GL_APIENTRYP PFNGLISSYNCAPPLEPROC) (GLsync sync); +typedef void (GL_APIENTRYP PFNGLDELETESYNCAPPLEPROC) (GLsync sync); +typedef GLenum (GL_APIENTRYP PFNGLCLIENTWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (GL_APIENTRYP PFNGLWAITSYNCAPPLEPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout); +typedef void (GL_APIENTRYP PFNGLGETINTEGER64VAPPLEPROC) (GLenum pname, GLint64 *params); +typedef void (GL_APIENTRYP PFNGLGETSYNCIVAPPLEPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values); +#endif + /* GL_APPLE_texture_format_BGRA8888 */ #ifndef GL_APPLE_texture_format_BGRA8888 #define GL_APPLE_texture_format_BGRA8888 1 @@ -1046,6 +1397,11 @@ typedef void (GL_APIENTRYP PFNGLRESOLVEMULTISAMPLEFRAMEBUFFERAPPLEPROC) (void); * ARM extension functions *------------------------------------------------------------------------*/ +/* GL_ARM_mali_program_binary */ +#ifndef GL_ARM_mali_program_binary +#define GL_ARM_mali_program_binary 1 +#endif + /* GL_ARM_mali_shader_binary */ #ifndef GL_ARM_mali_shader_binary #define GL_ARM_mali_shader_binary 1 @@ -1103,6 +1459,17 @@ GL_APICALL void GL_APIENTRY glDiscardFramebufferEXT (GLenum target, GLsizei numA typedef void (GL_APIENTRYP PFNGLDISCARDFRAMEBUFFEREXTPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments); #endif +/* GL_EXT_map_buffer_range */ +#ifndef GL_EXT_map_buffer_range +#define GL_EXT_map_buffer_range 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void* GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +GL_APICALL void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length); +#endif +typedef void* (GL_APIENTRYP PFNGLMAPBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +typedef void (GL_APIENTRYP PFNGLFLUSHMAPPEDBUFFERRANGEEXTPROC) (GLenum target, GLintptr offset, GLsizeiptr length); +#endif + /* GL_EXT_multisampled_render_to_texture */ #ifndef GL_EXT_multisampled_render_to_texture #define GL_EXT_multisampled_render_to_texture 1 @@ -1114,10 +1481,23 @@ typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC) (GLenum t typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEEXTPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); #endif +/* GL_EXT_multiview_draw_buffers */ +#ifndef GL_EXT_multiview_draw_buffers +#define GL_EXT_multiview_draw_buffers 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glReadBufferIndexedEXT (GLenum src, GLint index); +GL_APICALL void GL_APIENTRY glDrawBuffersIndexedEXT (GLint n, const GLenum *location, const GLint *indices); +GL_APICALL void GL_APIENTRY glGetIntegeri_vEXT (GLenum target, GLuint index, GLint *data); +#endif +typedef void (GL_APIENTRYP PFNGLREADBUFFERINDEXEDEXTPROC) (GLenum src, GLint index); +typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSINDEXEDEXTPROC) (GLint n, const GLenum *location, const GLint *indices); +typedef void (GL_APIENTRYP PFNGLGETINTEGERI_VEXTPROC) (GLenum target, GLuint index, GLint *data); +#endif + #ifndef GL_EXT_multi_draw_arrays #define GL_EXT_multi_draw_arrays 1 #ifdef GL_GLEXT_PROTOTYPES -GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum, GLint *, GLsizei *, GLsizei); +GL_APICALL void GL_APIENTRY glMultiDrawArraysEXT (GLenum, const GLint *, const GLsizei *, GLsizei); GL_APICALL void GL_APIENTRY glMultiDrawElementsEXT (GLenum, const GLsizei *, GLenum, const GLvoid* *, GLsizei); #endif /* GL_GLEXT_PROTOTYPES */ typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSEXTPROC) (GLenum mode, GLint *first, GLsizei *count, GLsizei primcount); @@ -1232,6 +1612,11 @@ typedef void (GL_APIENTRYP PFNGLVALIDATEPROGRAMPIPELINEEXTPROC) (GLuint pipeline typedef void (GL_APIENTRYP PFNGLGETPROGRAMPIPELINEINFOLOGEXTPROC) (GLuint pipeline, GLsizei bufSize, GLsizei *length, GLchar *infoLog); #endif +/* GL_EXT_shader_framebuffer_fetch */ +#ifndef GL_EXT_shader_framebuffer_fetch +#define GL_EXT_shader_framebuffer_fetch 1 +#endif + /* GL_EXT_shader_texture_lod */ #ifndef GL_EXT_shader_texture_lod #define GL_EXT_shader_texture_lod 1 @@ -1305,6 +1690,15 @@ typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum #define GL_DMP_shader_binary 1 #endif +/*------------------------------------------------------------------------* + * FJ extension functions + *------------------------------------------------------------------------*/ + +/* GL_FJ_shader_binary_GCCSO */ +#ifndef GL_FJ_shader_binary_GCCSO +#define GL_FJ_shader_binary_GCCSO 1 +#endif + /*------------------------------------------------------------------------* * IMG extension functions *------------------------------------------------------------------------*/ @@ -1329,6 +1723,11 @@ typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum #define GL_IMG_texture_compression_pvrtc 1 #endif +/* GL_IMG_texture_compression_pvrtc2 */ +#ifndef GL_IMG_texture_compression_pvrtc2 +#define GL_IMG_texture_compression_pvrtc2 1 +#endif + /* GL_IMG_multisampled_render_to_texture */ #ifndef GL_IMG_multisampled_render_to_texture #define GL_IMG_multisampled_render_to_texture 1 @@ -1336,8 +1735,8 @@ typedef void (GL_APIENTRYP PFNGLTEXTURESTORAGE3DEXTPROC) (GLuint texture, GLenum GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleIMG (GLenum, GLsizei, GLenum, GLsizei, GLsizei); GL_APICALL void GL_APIENTRY glFramebufferTexture2DMultisampleIMG (GLenum, GLenum, GLenum, GLuint, GLint, GLsizei); #endif -typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMG) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); -typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMG) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); +typedef void (GL_APIENTRYP PFNGLRENDERBUFFERSTORAGEMULTISAMPLEIMGPROC) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +typedef void (GL_APIENTRYP PFNGLFRAMEBUFFERTEXTURE2DMULTISAMPLEIMGPROC) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level, GLsizei samples); #endif /*------------------------------------------------------------------------* @@ -1369,6 +1768,7 @@ GL_APICALL void GL_APIENTRY glDrawBuffersNV (GLsizei n, const GLenum *bufs); typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSNVPROC) (GLsizei n, const GLenum *bufs); #endif +/* GL_EXT_draw_buffers */ #ifndef GL_EXT_draw_buffers #define GL_EXT_draw_buffers 1 #ifdef GL_GLEXT_PROTOTYPES @@ -1377,6 +1777,17 @@ GL_APICALL void GL_APIENTRY glDrawBuffersEXT (GLsizei n, const GLenum *bufs); typedef void (GL_APIENTRYP PFNGLDRAWBUFFERSEXTPROC) (GLsizei n, const GLenum *bufs); #endif +/* GL_NV_draw_instanced */ +#ifndef GL_NV_draw_instanced +#define GL_NV_draw_instanced 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glDrawArraysInstancedNV (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +GL_APICALL void GL_APIENTRY glDrawElementsInstancedNV (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); +#endif +typedef void (GL_APIENTRYP PFNDRAWARRAYSINSTANCEDNVPROC) (GLenum mode, GLint first, GLsizei count, GLsizei primcount); +typedef void (GL_APIENTRYP PFNDRAWELEMENTSINSTANCEDNVPROC) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount); +#endif + /* GL_NV_fbo_color_attachments */ #ifndef GL_NV_fbo_color_attachments #define GL_NV_fbo_color_attachments 1 @@ -1403,6 +1814,38 @@ typedef void (GL_APIENTRYP PFNGLFINISHFENCENVPROC) (GLuint fence); typedef void (GL_APIENTRYP PFNGLSETFENCENVPROC) (GLuint fence, GLenum condition); #endif +/* GL_NV_framebuffer_blit */ +#ifndef GL_NV_framebuffer_blit +#define GL_NV_framebuffer_blit 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glBlitFramebufferNV (int srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#endif +typedef void (GL_APIENTRYP PFNBLITFRAMEBUFFERNVPROC) (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +#endif + +/* GL_NV_framebuffer_multisample */ +#ifndef GL_NV_framebuffer_multisample +#define GL_NV_framebuffer_multisample 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisampleNV ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#endif +typedef void (GL_APIENTRYP PFNRENDERBUFFERSTORAGEMULTISAMPLENVPROC) ( GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +#endif + +/* GL_NV_generate_mipmap_sRGB */ +#ifndef GL_NV_generate_mipmap_sRGB +#define GL_NV_generate_mipmap_sRGB 1 +#endif + +/* GL_NV_instanced_arrays */ +#ifndef GL_NV_instanced_arrays +#define GL_NV_instanced_arrays 1 +#ifdef GL_GLEXT_PROTOTYPES +GL_APICALL void GL_APIENTRY glVertexAttribDivisorNV (GLuint index, GLuint divisor); +#endif +typedef void (GL_APIENTRYP PFNVERTEXATTRIBDIVISORNVPROC) (GLuint index, GLuint divisor); +#endif + /* GL_NV_read_buffer */ #ifndef GL_NV_read_buffer #define GL_NV_read_buffer 1 @@ -1432,6 +1875,26 @@ typedef void (GL_APIENTRYP PFNGLREADBUFFERNVPROC) (GLenum mode); #define GL_NV_read_stencil 1 #endif +/* GL_NV_shadow_samplers_array */ +#ifndef GL_NV_shadow_samplers_array +#define GL_NV_shadow_samplers_array 1 +#endif + +/* GL_NV_shadow_samplers_cube */ +#ifndef GL_NV_shadow_samplers_cube +#define GL_NV_shadow_samplers_cube 1 +#endif + +/* GL_NV_sRGB_formats */ +#ifndef GL_NV_sRGB_formats +#define GL_NV_sRGB_formats 1 +#endif + +/* GL_NV_texture_border_clamp */ +#ifndef GL_NV_texture_border_clamp +#define GL_NV_texture_border_clamp 1 +#endif + /* GL_NV_texture_compression_s3tc_update */ #ifndef GL_NV_texture_compression_s3tc_update #define GL_NV_texture_compression_s3tc_update 1 @@ -1455,6 +1918,11 @@ GL_APICALL void GL_APIENTRY glAlphaFuncQCOM (GLenum func, GLclampf ref); typedef void (GL_APIENTRYP PFNGLALPHAFUNCQCOMPROC) (GLenum func, GLclampf ref); #endif +/* GL_QCOM_binning_control */ +#ifndef GL_QCOM_binning_control +#define GL_QCOM_binning_control 1 +#endif + /* GL_QCOM_driver_control */ #ifndef GL_QCOM_driver_control #define GL_QCOM_driver_control 1 @@ -1538,11 +2006,6 @@ typedef void (GL_APIENTRYP PFNGLENDTILINGQCOMPROC) (GLbitfield preserveMask); #define GL_VIV_shader_binary 1 #endif -/* GL_ANGLE_program_binary */ -#ifndef GL_ANGLE_program_binary -#define GL_ANGLE_program_binary 1 -#endif - #ifdef __cplusplus } #endif diff --git a/src/3rdparty/angle/include/GLES3/gl3.h b/src/3rdparty/angle/include/GLES3/gl3.h new file mode 100644 index 0000000000..9c79862c0d --- /dev/null +++ b/src/3rdparty/angle/include/GLES3/gl3.h @@ -0,0 +1,1061 @@ +#ifndef __gl3_h_ +#define __gl3_h_ + +/* + * gl3.h last updated on $Date: 2013-02-12 14:37:24 -0800 (Tue, 12 Feb 2013) $ + */ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* +** Copyright (c) 2007-2013 The Khronos Group Inc. +** +** Permission is hereby granted, free of charge, to any person obtaining a +** copy of this software and/or associated documentation files (the +** "Materials"), to deal in the Materials without restriction, including +** without limitation the rights to use, copy, modify, merge, publish, +** distribute, sublicense, and/or sell copies of the Materials, and to +** permit persons to whom the Materials are furnished to do so, subject to +** the following conditions: +** +** The above copyright notice and this permission notice shall be included +** in all copies or substantial portions of the Materials. +** +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. +*/ + +/*------------------------------------------------------------------------- + * Data type definitions + *-----------------------------------------------------------------------*/ + +/* OpenGL ES 2.0 */ + +typedef void GLvoid; +typedef char GLchar; +typedef unsigned int GLenum; +typedef unsigned char GLboolean; +typedef unsigned int GLbitfield; +typedef khronos_int8_t GLbyte; +typedef short GLshort; +typedef int GLint; +typedef int GLsizei; +typedef khronos_uint8_t GLubyte; +typedef unsigned short GLushort; +typedef unsigned int GLuint; +typedef khronos_float_t GLfloat; +typedef khronos_float_t GLclampf; +typedef khronos_int32_t GLfixed; +typedef khronos_intptr_t GLintptr; +typedef khronos_ssize_t GLsizeiptr; + +/* OpenGL ES 3.0 */ + +typedef unsigned short GLhalf; +typedef khronos_int64_t GLint64; +typedef khronos_uint64_t GLuint64; +typedef struct __GLsync *GLsync; + +/*------------------------------------------------------------------------- + * Token definitions + *-----------------------------------------------------------------------*/ + +/* OpenGL ES core versions */ +#define GL_ES_VERSION_3_0 1 +#define GL_ES_VERSION_2_0 1 + +/* OpenGL ES 2.0 */ + +/* ClearBufferMask */ +#define GL_DEPTH_BUFFER_BIT 0x00000100 +#define GL_STENCIL_BUFFER_BIT 0x00000400 +#define GL_COLOR_BUFFER_BIT 0x00004000 + +/* Boolean */ +#define GL_FALSE 0 +#define GL_TRUE 1 + +/* BeginMode */ +#define GL_POINTS 0x0000 +#define GL_LINES 0x0001 +#define GL_LINE_LOOP 0x0002 +#define GL_LINE_STRIP 0x0003 +#define GL_TRIANGLES 0x0004 +#define GL_TRIANGLE_STRIP 0x0005 +#define GL_TRIANGLE_FAN 0x0006 + +/* BlendingFactorDest */ +#define GL_ZERO 0 +#define GL_ONE 1 +#define GL_SRC_COLOR 0x0300 +#define GL_ONE_MINUS_SRC_COLOR 0x0301 +#define GL_SRC_ALPHA 0x0302 +#define GL_ONE_MINUS_SRC_ALPHA 0x0303 +#define GL_DST_ALPHA 0x0304 +#define GL_ONE_MINUS_DST_ALPHA 0x0305 + +/* BlendingFactorSrc */ +/* GL_ZERO */ +/* GL_ONE */ +#define GL_DST_COLOR 0x0306 +#define GL_ONE_MINUS_DST_COLOR 0x0307 +#define GL_SRC_ALPHA_SATURATE 0x0308 +/* GL_SRC_ALPHA */ +/* GL_ONE_MINUS_SRC_ALPHA */ +/* GL_DST_ALPHA */ +/* GL_ONE_MINUS_DST_ALPHA */ + +/* BlendEquationSeparate */ +#define GL_FUNC_ADD 0x8006 +#define GL_BLEND_EQUATION 0x8009 +#define GL_BLEND_EQUATION_RGB 0x8009 /* same as BLEND_EQUATION */ +#define GL_BLEND_EQUATION_ALPHA 0x883D + +/* BlendSubtract */ +#define GL_FUNC_SUBTRACT 0x800A +#define GL_FUNC_REVERSE_SUBTRACT 0x800B + +/* Separate Blend Functions */ +#define GL_BLEND_DST_RGB 0x80C8 +#define GL_BLEND_SRC_RGB 0x80C9 +#define GL_BLEND_DST_ALPHA 0x80CA +#define GL_BLEND_SRC_ALPHA 0x80CB +#define GL_CONSTANT_COLOR 0x8001 +#define GL_ONE_MINUS_CONSTANT_COLOR 0x8002 +#define GL_CONSTANT_ALPHA 0x8003 +#define GL_ONE_MINUS_CONSTANT_ALPHA 0x8004 +#define GL_BLEND_COLOR 0x8005 + +/* Buffer Objects */ +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#define GL_ARRAY_BUFFER_BINDING 0x8894 +#define GL_ELEMENT_ARRAY_BUFFER_BINDING 0x8895 + +#define GL_STREAM_DRAW 0x88E0 +#define GL_STATIC_DRAW 0x88E4 +#define GL_DYNAMIC_DRAW 0x88E8 + +#define GL_BUFFER_SIZE 0x8764 +#define GL_BUFFER_USAGE 0x8765 + +#define GL_CURRENT_VERTEX_ATTRIB 0x8626 + +/* CullFaceMode */ +#define GL_FRONT 0x0404 +#define GL_BACK 0x0405 +#define GL_FRONT_AND_BACK 0x0408 + +/* DepthFunction */ +/* GL_NEVER */ +/* GL_LESS */ +/* GL_EQUAL */ +/* GL_LEQUAL */ +/* GL_GREATER */ +/* GL_NOTEQUAL */ +/* GL_GEQUAL */ +/* GL_ALWAYS */ + +/* EnableCap */ +#define GL_TEXTURE_2D 0x0DE1 +#define GL_CULL_FACE 0x0B44 +#define GL_BLEND 0x0BE2 +#define GL_DITHER 0x0BD0 +#define GL_STENCIL_TEST 0x0B90 +#define GL_DEPTH_TEST 0x0B71 +#define GL_SCISSOR_TEST 0x0C11 +#define GL_POLYGON_OFFSET_FILL 0x8037 +#define GL_SAMPLE_ALPHA_TO_COVERAGE 0x809E +#define GL_SAMPLE_COVERAGE 0x80A0 + +/* ErrorCode */ +#define GL_NO_ERROR 0 +#define GL_INVALID_ENUM 0x0500 +#define GL_INVALID_VALUE 0x0501 +#define GL_INVALID_OPERATION 0x0502 +#define GL_OUT_OF_MEMORY 0x0505 + +/* FrontFaceDirection */ +#define GL_CW 0x0900 +#define GL_CCW 0x0901 + +/* GetPName */ +#define GL_LINE_WIDTH 0x0B21 +#define GL_ALIASED_POINT_SIZE_RANGE 0x846D +#define GL_ALIASED_LINE_WIDTH_RANGE 0x846E +#define GL_CULL_FACE_MODE 0x0B45 +#define GL_FRONT_FACE 0x0B46 +#define GL_DEPTH_RANGE 0x0B70 +#define GL_DEPTH_WRITEMASK 0x0B72 +#define GL_DEPTH_CLEAR_VALUE 0x0B73 +#define GL_DEPTH_FUNC 0x0B74 +#define GL_STENCIL_CLEAR_VALUE 0x0B91 +#define GL_STENCIL_FUNC 0x0B92 +#define GL_STENCIL_FAIL 0x0B94 +#define GL_STENCIL_PASS_DEPTH_FAIL 0x0B95 +#define GL_STENCIL_PASS_DEPTH_PASS 0x0B96 +#define GL_STENCIL_REF 0x0B97 +#define GL_STENCIL_VALUE_MASK 0x0B93 +#define GL_STENCIL_WRITEMASK 0x0B98 +#define GL_STENCIL_BACK_FUNC 0x8800 +#define GL_STENCIL_BACK_FAIL 0x8801 +#define GL_STENCIL_BACK_PASS_DEPTH_FAIL 0x8802 +#define GL_STENCIL_BACK_PASS_DEPTH_PASS 0x8803 +#define GL_STENCIL_BACK_REF 0x8CA3 +#define GL_STENCIL_BACK_VALUE_MASK 0x8CA4 +#define GL_STENCIL_BACK_WRITEMASK 0x8CA5 +#define GL_VIEWPORT 0x0BA2 +#define GL_SCISSOR_BOX 0x0C10 +/* GL_SCISSOR_TEST */ +#define GL_COLOR_CLEAR_VALUE 0x0C22 +#define GL_COLOR_WRITEMASK 0x0C23 +#define GL_UNPACK_ALIGNMENT 0x0CF5 +#define GL_PACK_ALIGNMENT 0x0D05 +#define GL_MAX_TEXTURE_SIZE 0x0D33 +#define GL_MAX_VIEWPORT_DIMS 0x0D3A +#define GL_SUBPIXEL_BITS 0x0D50 +#define GL_RED_BITS 0x0D52 +#define GL_GREEN_BITS 0x0D53 +#define GL_BLUE_BITS 0x0D54 +#define GL_ALPHA_BITS 0x0D55 +#define GL_DEPTH_BITS 0x0D56 +#define GL_STENCIL_BITS 0x0D57 +#define GL_POLYGON_OFFSET_UNITS 0x2A00 +/* GL_POLYGON_OFFSET_FILL */ +#define GL_POLYGON_OFFSET_FACTOR 0x8038 +#define GL_TEXTURE_BINDING_2D 0x8069 +#define GL_SAMPLE_BUFFERS 0x80A8 +#define GL_SAMPLES 0x80A9 +#define GL_SAMPLE_COVERAGE_VALUE 0x80AA +#define GL_SAMPLE_COVERAGE_INVERT 0x80AB + +/* GetTextureParameter */ +/* GL_TEXTURE_MAG_FILTER */ +/* GL_TEXTURE_MIN_FILTER */ +/* GL_TEXTURE_WRAP_S */ +/* GL_TEXTURE_WRAP_T */ + +#define GL_NUM_COMPRESSED_TEXTURE_FORMATS 0x86A2 +#define GL_COMPRESSED_TEXTURE_FORMATS 0x86A3 + +/* HintMode */ +#define GL_DONT_CARE 0x1100 +#define GL_FASTEST 0x1101 +#define GL_NICEST 0x1102 + +/* HintTarget */ +#define GL_GENERATE_MIPMAP_HINT 0x8192 + +/* DataType */ +#define GL_BYTE 0x1400 +#define GL_UNSIGNED_BYTE 0x1401 +#define GL_SHORT 0x1402 +#define GL_UNSIGNED_SHORT 0x1403 +#define GL_INT 0x1404 +#define GL_UNSIGNED_INT 0x1405 +#define GL_FLOAT 0x1406 +#define GL_FIXED 0x140C + +/* PixelFormat */ +#define GL_DEPTH_COMPONENT 0x1902 +#define GL_ALPHA 0x1906 +#define GL_RGB 0x1907 +#define GL_RGBA 0x1908 +#define GL_LUMINANCE 0x1909 +#define GL_LUMINANCE_ALPHA 0x190A + +/* PixelType */ +/* GL_UNSIGNED_BYTE */ +#define GL_UNSIGNED_SHORT_4_4_4_4 0x8033 +#define GL_UNSIGNED_SHORT_5_5_5_1 0x8034 +#define GL_UNSIGNED_SHORT_5_6_5 0x8363 + +/* Shaders */ +#define GL_FRAGMENT_SHADER 0x8B30 +#define GL_VERTEX_SHADER 0x8B31 +#define GL_MAX_VERTEX_ATTRIBS 0x8869 +#define GL_MAX_VERTEX_UNIFORM_VECTORS 0x8DFB +#define GL_MAX_VARYING_VECTORS 0x8DFC +#define GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS 0x8B4D +#define GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS 0x8B4C +#define GL_MAX_TEXTURE_IMAGE_UNITS 0x8872 +#define GL_MAX_FRAGMENT_UNIFORM_VECTORS 0x8DFD +#define GL_SHADER_TYPE 0x8B4F +#define GL_DELETE_STATUS 0x8B80 +#define GL_LINK_STATUS 0x8B82 +#define GL_VALIDATE_STATUS 0x8B83 +#define GL_ATTACHED_SHADERS 0x8B85 +#define GL_ACTIVE_UNIFORMS 0x8B86 +#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87 +#define GL_ACTIVE_ATTRIBUTES 0x8B89 +#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A +#define GL_SHADING_LANGUAGE_VERSION 0x8B8C +#define GL_CURRENT_PROGRAM 0x8B8D + +/* StencilFunction */ +#define GL_NEVER 0x0200 +#define GL_LESS 0x0201 +#define GL_EQUAL 0x0202 +#define GL_LEQUAL 0x0203 +#define GL_GREATER 0x0204 +#define GL_NOTEQUAL 0x0205 +#define GL_GEQUAL 0x0206 +#define GL_ALWAYS 0x0207 + +/* StencilOp */ +/* GL_ZERO */ +#define GL_KEEP 0x1E00 +#define GL_REPLACE 0x1E01 +#define GL_INCR 0x1E02 +#define GL_DECR 0x1E03 +#define GL_INVERT 0x150A +#define GL_INCR_WRAP 0x8507 +#define GL_DECR_WRAP 0x8508 + +/* StringName */ +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 +#define GL_VERSION 0x1F02 +#define GL_EXTENSIONS 0x1F03 + +/* TextureMagFilter */ +#define GL_NEAREST 0x2600 +#define GL_LINEAR 0x2601 + +/* TextureMinFilter */ +/* GL_NEAREST */ +/* GL_LINEAR */ +#define GL_NEAREST_MIPMAP_NEAREST 0x2700 +#define GL_LINEAR_MIPMAP_NEAREST 0x2701 +#define GL_NEAREST_MIPMAP_LINEAR 0x2702 +#define GL_LINEAR_MIPMAP_LINEAR 0x2703 + +/* TextureParameterName */ +#define GL_TEXTURE_MAG_FILTER 0x2800 +#define GL_TEXTURE_MIN_FILTER 0x2801 +#define GL_TEXTURE_WRAP_S 0x2802 +#define GL_TEXTURE_WRAP_T 0x2803 + +/* TextureTarget */ +/* GL_TEXTURE_2D */ +#define GL_TEXTURE 0x1702 + +#define GL_TEXTURE_CUBE_MAP 0x8513 +#define GL_TEXTURE_BINDING_CUBE_MAP 0x8514 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_X 0x8515 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_X 0x8516 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Y 0x8517 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x8518 +#define GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x8519 +#define GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x851A +#define GL_MAX_CUBE_MAP_TEXTURE_SIZE 0x851C + +/* TextureUnit */ +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#define GL_ACTIVE_TEXTURE 0x84E0 + +/* TextureWrapMode */ +#define GL_REPEAT 0x2901 +#define GL_CLAMP_TO_EDGE 0x812F +#define GL_MIRRORED_REPEAT 0x8370 + +/* Uniform Types */ +#define GL_FLOAT_VEC2 0x8B50 +#define GL_FLOAT_VEC3 0x8B51 +#define GL_FLOAT_VEC4 0x8B52 +#define GL_INT_VEC2 0x8B53 +#define GL_INT_VEC3 0x8B54 +#define GL_INT_VEC4 0x8B55 +#define GL_BOOL 0x8B56 +#define GL_BOOL_VEC2 0x8B57 +#define GL_BOOL_VEC3 0x8B58 +#define GL_BOOL_VEC4 0x8B59 +#define GL_FLOAT_MAT2 0x8B5A +#define GL_FLOAT_MAT3 0x8B5B +#define GL_FLOAT_MAT4 0x8B5C +#define GL_SAMPLER_2D 0x8B5E +#define GL_SAMPLER_CUBE 0x8B60 + +/* Vertex Arrays */ +#define GL_VERTEX_ATTRIB_ARRAY_ENABLED 0x8622 +#define GL_VERTEX_ATTRIB_ARRAY_SIZE 0x8623 +#define GL_VERTEX_ATTRIB_ARRAY_STRIDE 0x8624 +#define GL_VERTEX_ATTRIB_ARRAY_TYPE 0x8625 +#define GL_VERTEX_ATTRIB_ARRAY_NORMALIZED 0x886A +#define GL_VERTEX_ATTRIB_ARRAY_POINTER 0x8645 +#define GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING 0x889F + +/* Read Format */ +#define GL_IMPLEMENTATION_COLOR_READ_TYPE 0x8B9A +#define GL_IMPLEMENTATION_COLOR_READ_FORMAT 0x8B9B + +/* Shader Source */ +#define GL_COMPILE_STATUS 0x8B81 +#define GL_INFO_LOG_LENGTH 0x8B84 +#define GL_SHADER_SOURCE_LENGTH 0x8B88 +#define GL_SHADER_COMPILER 0x8DFA + +/* Shader Binary */ +#define GL_SHADER_BINARY_FORMATS 0x8DF8 +#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9 + +/* Shader Precision-Specified Types */ +#define GL_LOW_FLOAT 0x8DF0 +#define GL_MEDIUM_FLOAT 0x8DF1 +#define GL_HIGH_FLOAT 0x8DF2 +#define GL_LOW_INT 0x8DF3 +#define GL_MEDIUM_INT 0x8DF4 +#define GL_HIGH_INT 0x8DF5 + +/* Framebuffer Object. */ +#define GL_FRAMEBUFFER 0x8D40 +#define GL_RENDERBUFFER 0x8D41 + +#define GL_RGBA4 0x8056 +#define GL_RGB5_A1 0x8057 +#define GL_RGB565 0x8D62 +#define GL_DEPTH_COMPONENT16 0x81A5 +#define GL_STENCIL_INDEX8 0x8D48 + +#define GL_RENDERBUFFER_WIDTH 0x8D42 +#define GL_RENDERBUFFER_HEIGHT 0x8D43 +#define GL_RENDERBUFFER_INTERNAL_FORMAT 0x8D44 +#define GL_RENDERBUFFER_RED_SIZE 0x8D50 +#define GL_RENDERBUFFER_GREEN_SIZE 0x8D51 +#define GL_RENDERBUFFER_BLUE_SIZE 0x8D52 +#define GL_RENDERBUFFER_ALPHA_SIZE 0x8D53 +#define GL_RENDERBUFFER_DEPTH_SIZE 0x8D54 +#define GL_RENDERBUFFER_STENCIL_SIZE 0x8D55 + +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE 0x8CD0 +#define GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME 0x8CD1 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL 0x8CD2 +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE 0x8CD3 + +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_STENCIL_ATTACHMENT 0x8D20 + +#define GL_NONE 0 + +#define GL_FRAMEBUFFER_COMPLETE 0x8CD5 +#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT 0x8CD6 +#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT 0x8CD7 +#define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 +#define GL_FRAMEBUFFER_UNSUPPORTED 0x8CDD + +#define GL_FRAMEBUFFER_BINDING 0x8CA6 +#define GL_RENDERBUFFER_BINDING 0x8CA7 +#define GL_MAX_RENDERBUFFER_SIZE 0x84E8 + +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 + +/* OpenGL ES 3.0 */ + +#define GL_READ_BUFFER 0x0C02 +#define GL_UNPACK_ROW_LENGTH 0x0CF2 +#define GL_UNPACK_SKIP_ROWS 0x0CF3 +#define GL_UNPACK_SKIP_PIXELS 0x0CF4 +#define GL_PACK_ROW_LENGTH 0x0D02 +#define GL_PACK_SKIP_ROWS 0x0D03 +#define GL_PACK_SKIP_PIXELS 0x0D04 +#define GL_COLOR 0x1800 +#define GL_DEPTH 0x1801 +#define GL_STENCIL 0x1802 +#define GL_RED 0x1903 +#define GL_RGB8 0x8051 +#define GL_RGBA8 0x8058 +#define GL_RGB10_A2 0x8059 +#define GL_TEXTURE_BINDING_3D 0x806A +#define GL_UNPACK_SKIP_IMAGES 0x806D +#define GL_UNPACK_IMAGE_HEIGHT 0x806E +#define GL_TEXTURE_3D 0x806F +#define GL_TEXTURE_WRAP_R 0x8072 +#define GL_MAX_3D_TEXTURE_SIZE 0x8073 +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#define GL_MAX_ELEMENTS_VERTICES 0x80E8 +#define GL_MAX_ELEMENTS_INDICES 0x80E9 +#define GL_TEXTURE_MIN_LOD 0x813A +#define GL_TEXTURE_MAX_LOD 0x813B +#define GL_TEXTURE_BASE_LEVEL 0x813C +#define GL_TEXTURE_MAX_LEVEL 0x813D +#define GL_MIN 0x8007 +#define GL_MAX 0x8008 +#define GL_DEPTH_COMPONENT24 0x81A6 +#define GL_MAX_TEXTURE_LOD_BIAS 0x84FD +#define GL_TEXTURE_COMPARE_MODE 0x884C +#define GL_TEXTURE_COMPARE_FUNC 0x884D +#define GL_CURRENT_QUERY 0x8865 +#define GL_QUERY_RESULT 0x8866 +#define GL_QUERY_RESULT_AVAILABLE 0x8867 +#define GL_BUFFER_MAPPED 0x88BC +#define GL_BUFFER_MAP_POINTER 0x88BD +#define GL_STREAM_READ 0x88E1 +#define GL_STREAM_COPY 0x88E2 +#define GL_STATIC_READ 0x88E5 +#define GL_STATIC_COPY 0x88E6 +#define GL_DYNAMIC_READ 0x88E9 +#define GL_DYNAMIC_COPY 0x88EA +#define GL_MAX_DRAW_BUFFERS 0x8824 +#define GL_DRAW_BUFFER0 0x8825 +#define GL_DRAW_BUFFER1 0x8826 +#define GL_DRAW_BUFFER2 0x8827 +#define GL_DRAW_BUFFER3 0x8828 +#define GL_DRAW_BUFFER4 0x8829 +#define GL_DRAW_BUFFER5 0x882A +#define GL_DRAW_BUFFER6 0x882B +#define GL_DRAW_BUFFER7 0x882C +#define GL_DRAW_BUFFER8 0x882D +#define GL_DRAW_BUFFER9 0x882E +#define GL_DRAW_BUFFER10 0x882F +#define GL_DRAW_BUFFER11 0x8830 +#define GL_DRAW_BUFFER12 0x8831 +#define GL_DRAW_BUFFER13 0x8832 +#define GL_DRAW_BUFFER14 0x8833 +#define GL_DRAW_BUFFER15 0x8834 +#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS 0x8B49 +#define GL_MAX_VERTEX_UNIFORM_COMPONENTS 0x8B4A +#define GL_SAMPLER_3D 0x8B5F +#define GL_SAMPLER_2D_SHADOW 0x8B62 +#define GL_FRAGMENT_SHADER_DERIVATIVE_HINT 0x8B8B +#define GL_PIXEL_PACK_BUFFER 0x88EB +#define GL_PIXEL_UNPACK_BUFFER 0x88EC +#define GL_PIXEL_PACK_BUFFER_BINDING 0x88ED +#define GL_PIXEL_UNPACK_BUFFER_BINDING 0x88EF +#define GL_FLOAT_MAT2x3 0x8B65 +#define GL_FLOAT_MAT2x4 0x8B66 +#define GL_FLOAT_MAT3x2 0x8B67 +#define GL_FLOAT_MAT3x4 0x8B68 +#define GL_FLOAT_MAT4x2 0x8B69 +#define GL_FLOAT_MAT4x3 0x8B6A +#define GL_SRGB 0x8C40 +#define GL_SRGB8 0x8C41 +#define GL_SRGB8_ALPHA8 0x8C43 +#define GL_COMPARE_REF_TO_TEXTURE 0x884E +#define GL_MAJOR_VERSION 0x821B +#define GL_MINOR_VERSION 0x821C +#define GL_NUM_EXTENSIONS 0x821D +#define GL_RGBA32F 0x8814 +#define GL_RGB32F 0x8815 +#define GL_RGBA16F 0x881A +#define GL_RGB16F 0x881B +#define GL_VERTEX_ATTRIB_ARRAY_INTEGER 0x88FD +#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF +#define GL_MIN_PROGRAM_TEXEL_OFFSET 0x8904 +#define GL_MAX_PROGRAM_TEXEL_OFFSET 0x8905 +#define GL_MAX_VARYING_COMPONENTS 0x8B4B +#define GL_TEXTURE_2D_ARRAY 0x8C1A +#define GL_TEXTURE_BINDING_2D_ARRAY 0x8C1D +#define GL_R11F_G11F_B10F 0x8C3A +#define GL_UNSIGNED_INT_10F_11F_11F_REV 0x8C3B +#define GL_RGB9_E5 0x8C3D +#define GL_UNSIGNED_INT_5_9_9_9_REV 0x8C3E +#define GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH 0x8C76 +#define GL_TRANSFORM_FEEDBACK_BUFFER_MODE 0x8C7F +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS 0x8C80 +#define GL_TRANSFORM_FEEDBACK_VARYINGS 0x8C83 +#define GL_TRANSFORM_FEEDBACK_BUFFER_START 0x8C84 +#define GL_TRANSFORM_FEEDBACK_BUFFER_SIZE 0x8C85 +#define GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN 0x8C88 +#define GL_RASTERIZER_DISCARD 0x8C89 +#define GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS 0x8C8A +#define GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS 0x8C8B +#define GL_INTERLEAVED_ATTRIBS 0x8C8C +#define GL_SEPARATE_ATTRIBS 0x8C8D +#define GL_TRANSFORM_FEEDBACK_BUFFER 0x8C8E +#define GL_TRANSFORM_FEEDBACK_BUFFER_BINDING 0x8C8F +#define GL_RGBA32UI 0x8D70 +#define GL_RGB32UI 0x8D71 +#define GL_RGBA16UI 0x8D76 +#define GL_RGB16UI 0x8D77 +#define GL_RGBA8UI 0x8D7C +#define GL_RGB8UI 0x8D7D +#define GL_RGBA32I 0x8D82 +#define GL_RGB32I 0x8D83 +#define GL_RGBA16I 0x8D88 +#define GL_RGB16I 0x8D89 +#define GL_RGBA8I 0x8D8E +#define GL_RGB8I 0x8D8F +#define GL_RED_INTEGER 0x8D94 +#define GL_RGB_INTEGER 0x8D98 +#define GL_RGBA_INTEGER 0x8D99 +#define GL_SAMPLER_2D_ARRAY 0x8DC1 +#define GL_SAMPLER_2D_ARRAY_SHADOW 0x8DC4 +#define GL_SAMPLER_CUBE_SHADOW 0x8DC5 +#define GL_UNSIGNED_INT_VEC2 0x8DC6 +#define GL_UNSIGNED_INT_VEC3 0x8DC7 +#define GL_UNSIGNED_INT_VEC4 0x8DC8 +#define GL_INT_SAMPLER_2D 0x8DCA +#define GL_INT_SAMPLER_3D 0x8DCB +#define GL_INT_SAMPLER_CUBE 0x8DCC +#define GL_INT_SAMPLER_2D_ARRAY 0x8DCF +#define GL_UNSIGNED_INT_SAMPLER_2D 0x8DD2 +#define GL_UNSIGNED_INT_SAMPLER_3D 0x8DD3 +#define GL_UNSIGNED_INT_SAMPLER_CUBE 0x8DD4 +#define GL_UNSIGNED_INT_SAMPLER_2D_ARRAY 0x8DD7 +#define GL_BUFFER_ACCESS_FLAGS 0x911F +#define GL_BUFFER_MAP_LENGTH 0x9120 +#define GL_BUFFER_MAP_OFFSET 0x9121 +#define GL_DEPTH_COMPONENT32F 0x8CAC +#define GL_DEPTH32F_STENCIL8 0x8CAD +#define GL_FLOAT_32_UNSIGNED_INT_24_8_REV 0x8DAD +#define GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 0x8210 +#define GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE 0x8211 +#define GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE 0x8212 +#define GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE 0x8213 +#define GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE 0x8214 +#define GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE 0x8215 +#define GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE 0x8216 +#define GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE 0x8217 +#define GL_FRAMEBUFFER_DEFAULT 0x8218 +#define GL_FRAMEBUFFER_UNDEFINED 0x8219 +#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A +#define GL_DEPTH_STENCIL 0x84F9 +#define GL_UNSIGNED_INT_24_8 0x84FA +#define GL_DEPTH24_STENCIL8 0x88F0 +#define GL_UNSIGNED_NORMALIZED 0x8C17 +#define GL_DRAW_FRAMEBUFFER_BINDING GL_FRAMEBUFFER_BINDING +#define GL_READ_FRAMEBUFFER 0x8CA8 +#define GL_DRAW_FRAMEBUFFER 0x8CA9 +#define GL_READ_FRAMEBUFFER_BINDING 0x8CAA +#define GL_RENDERBUFFER_SAMPLES 0x8CAB +#define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER 0x8CD4 +#define GL_MAX_COLOR_ATTACHMENTS 0x8CDF +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE 0x8D56 +#define GL_MAX_SAMPLES 0x8D57 +#define GL_HALF_FLOAT 0x140B +#define GL_MAP_READ_BIT 0x0001 +#define GL_MAP_WRITE_BIT 0x0002 +#define GL_MAP_INVALIDATE_RANGE_BIT 0x0004 +#define GL_MAP_INVALIDATE_BUFFER_BIT 0x0008 +#define GL_MAP_FLUSH_EXPLICIT_BIT 0x0010 +#define GL_MAP_UNSYNCHRONIZED_BIT 0x0020 +#define GL_RG 0x8227 +#define GL_RG_INTEGER 0x8228 +#define GL_R8 0x8229 +#define GL_RG8 0x822B +#define GL_R16F 0x822D +#define GL_R32F 0x822E +#define GL_RG16F 0x822F +#define GL_RG32F 0x8230 +#define GL_R8I 0x8231 +#define GL_R8UI 0x8232 +#define GL_R16I 0x8233 +#define GL_R16UI 0x8234 +#define GL_R32I 0x8235 +#define GL_R32UI 0x8236 +#define GL_RG8I 0x8237 +#define GL_RG8UI 0x8238 +#define GL_RG16I 0x8239 +#define GL_RG16UI 0x823A +#define GL_RG32I 0x823B +#define GL_RG32UI 0x823C +#define GL_VERTEX_ARRAY_BINDING 0x85B5 +#define GL_R8_SNORM 0x8F94 +#define GL_RG8_SNORM 0x8F95 +#define GL_RGB8_SNORM 0x8F96 +#define GL_RGBA8_SNORM 0x8F97 +#define GL_SIGNED_NORMALIZED 0x8F9C +#define GL_PRIMITIVE_RESTART_FIXED_INDEX 0x8D69 +#define GL_COPY_READ_BUFFER 0x8F36 +#define GL_COPY_WRITE_BUFFER 0x8F37 +#define GL_COPY_READ_BUFFER_BINDING GL_COPY_READ_BUFFER +#define GL_COPY_WRITE_BUFFER_BINDING GL_COPY_WRITE_BUFFER +#define GL_UNIFORM_BUFFER 0x8A11 +#define GL_UNIFORM_BUFFER_BINDING 0x8A28 +#define GL_UNIFORM_BUFFER_START 0x8A29 +#define GL_UNIFORM_BUFFER_SIZE 0x8A2A +#define GL_MAX_VERTEX_UNIFORM_BLOCKS 0x8A2B +#define GL_MAX_FRAGMENT_UNIFORM_BLOCKS 0x8A2D +#define GL_MAX_COMBINED_UNIFORM_BLOCKS 0x8A2E +#define GL_MAX_UNIFORM_BUFFER_BINDINGS 0x8A2F +#define GL_MAX_UNIFORM_BLOCK_SIZE 0x8A30 +#define GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS 0x8A31 +#define GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS 0x8A33 +#define GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT 0x8A34 +#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35 +#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36 +#define GL_UNIFORM_TYPE 0x8A37 +#define GL_UNIFORM_SIZE 0x8A38 +#define GL_UNIFORM_NAME_LENGTH 0x8A39 +#define GL_UNIFORM_BLOCK_INDEX 0x8A3A +#define GL_UNIFORM_OFFSET 0x8A3B +#define GL_UNIFORM_ARRAY_STRIDE 0x8A3C +#define GL_UNIFORM_MATRIX_STRIDE 0x8A3D +#define GL_UNIFORM_IS_ROW_MAJOR 0x8A3E +#define GL_UNIFORM_BLOCK_BINDING 0x8A3F +#define GL_UNIFORM_BLOCK_DATA_SIZE 0x8A40 +#define GL_UNIFORM_BLOCK_NAME_LENGTH 0x8A41 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS 0x8A42 +#define GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES 0x8A43 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER 0x8A44 +#define GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER 0x8A46 +#define GL_INVALID_INDEX 0xFFFFFFFFu +#define GL_MAX_VERTEX_OUTPUT_COMPONENTS 0x9122 +#define GL_MAX_FRAGMENT_INPUT_COMPONENTS 0x9125 +#define GL_MAX_SERVER_WAIT_TIMEOUT 0x9111 +#define GL_OBJECT_TYPE 0x9112 +#define GL_SYNC_CONDITION 0x9113 +#define GL_SYNC_STATUS 0x9114 +#define GL_SYNC_FLAGS 0x9115 +#define GL_SYNC_FENCE 0x9116 +#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117 +#define GL_UNSIGNALED 0x9118 +#define GL_SIGNALED 0x9119 +#define GL_ALREADY_SIGNALED 0x911A +#define GL_TIMEOUT_EXPIRED 0x911B +#define GL_CONDITION_SATISFIED 0x911C +#define GL_WAIT_FAILED 0x911D +#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001 +#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull +#define GL_VERTEX_ATTRIB_ARRAY_DIVISOR 0x88FE +#define GL_ANY_SAMPLES_PASSED 0x8C2F +#define GL_ANY_SAMPLES_PASSED_CONSERVATIVE 0x8D6A +#define GL_SAMPLER_BINDING 0x8919 +#define GL_RGB10_A2UI 0x906F +#define GL_TEXTURE_SWIZZLE_R 0x8E42 +#define GL_TEXTURE_SWIZZLE_G 0x8E43 +#define GL_TEXTURE_SWIZZLE_B 0x8E44 +#define GL_TEXTURE_SWIZZLE_A 0x8E45 +#define GL_GREEN 0x1904 +#define GL_BLUE 0x1905 +#define GL_INT_2_10_10_10_REV 0x8D9F +#define GL_TRANSFORM_FEEDBACK 0x8E22 +#define GL_TRANSFORM_FEEDBACK_PAUSED 0x8E23 +#define GL_TRANSFORM_FEEDBACK_ACTIVE 0x8E24 +#define GL_TRANSFORM_FEEDBACK_BINDING 0x8E25 +#define GL_PROGRAM_BINARY_RETRIEVABLE_HINT 0x8257 +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF +#define GL_COMPRESSED_R11_EAC 0x9270 +#define GL_COMPRESSED_SIGNED_R11_EAC 0x9271 +#define GL_COMPRESSED_RG11_EAC 0x9272 +#define GL_COMPRESSED_SIGNED_RG11_EAC 0x9273 +#define GL_COMPRESSED_RGB8_ETC2 0x9274 +#define GL_COMPRESSED_SRGB8_ETC2 0x9275 +#define GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9276 +#define GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 0x9277 +#define GL_COMPRESSED_RGBA8_ETC2_EAC 0x9278 +#define GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 0x9279 +#define GL_TEXTURE_IMMUTABLE_FORMAT 0x912F +#define GL_MAX_ELEMENT_INDEX 0x8D6B +#define GL_NUM_SAMPLE_COUNTS 0x9380 +#define GL_TEXTURE_IMMUTABLE_LEVELS 0x82DF + +/*------------------------------------------------------------------------- + * Entrypoint definitions + *-----------------------------------------------------------------------*/ + +/* OpenGL ES 2.0 */ + +GL_APICALL void GL_APIENTRY glActiveTexture (GLenum texture); +GL_APICALL void GL_APIENTRY glAttachShader (GLuint program, GLuint shader); +GL_APICALL void GL_APIENTRY glBindAttribLocation (GLuint program, GLuint index, const GLchar* name); +GL_APICALL void GL_APIENTRY glBindBuffer (GLenum target, GLuint buffer); +GL_APICALL void GL_APIENTRY glBindFramebuffer (GLenum target, GLuint framebuffer); +GL_APICALL void GL_APIENTRY glBindRenderbuffer (GLenum target, GLuint renderbuffer); +GL_APICALL void GL_APIENTRY glBindTexture (GLenum target, GLuint texture); +GL_APICALL void GL_APIENTRY glBlendColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GL_APICALL void GL_APIENTRY glBlendEquation (GLenum mode); +GL_APICALL void GL_APIENTRY glBlendEquationSeparate (GLenum modeRGB, GLenum modeAlpha); +GL_APICALL void GL_APIENTRY glBlendFunc (GLenum sfactor, GLenum dfactor); +GL_APICALL void GL_APIENTRY glBlendFuncSeparate (GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha); +GL_APICALL void GL_APIENTRY glBufferData (GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage); +GL_APICALL void GL_APIENTRY glBufferSubData (GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data); +GL_APICALL GLenum GL_APIENTRY glCheckFramebufferStatus (GLenum target); +GL_APICALL void GL_APIENTRY glClear (GLbitfield mask); +GL_APICALL void GL_APIENTRY glClearColor (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha); +GL_APICALL void GL_APIENTRY glClearDepthf (GLfloat depth); +GL_APICALL void GL_APIENTRY glClearStencil (GLint s); +GL_APICALL void GL_APIENTRY glColorMask (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); +GL_APICALL void GL_APIENTRY glCompileShader (GLuint shader); +GL_APICALL void GL_APIENTRY glCompressedTexImage2D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data); +GL_APICALL void GL_APIENTRY glCompressedTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data); +GL_APICALL void GL_APIENTRY glCopyTexImage2D (GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border); +GL_APICALL void GL_APIENTRY glCopyTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL GLuint GL_APIENTRY glCreateProgram (void); +GL_APICALL GLuint GL_APIENTRY glCreateShader (GLenum type); +GL_APICALL void GL_APIENTRY glCullFace (GLenum mode); +GL_APICALL void GL_APIENTRY glDeleteBuffers (GLsizei n, const GLuint* buffers); +GL_APICALL void GL_APIENTRY glDeleteFramebuffers (GLsizei n, const GLuint* framebuffers); +GL_APICALL void GL_APIENTRY glDeleteProgram (GLuint program); +GL_APICALL void GL_APIENTRY glDeleteRenderbuffers (GLsizei n, const GLuint* renderbuffers); +GL_APICALL void GL_APIENTRY glDeleteShader (GLuint shader); +GL_APICALL void GL_APIENTRY glDeleteTextures (GLsizei n, const GLuint* textures); +GL_APICALL void GL_APIENTRY glDepthFunc (GLenum func); +GL_APICALL void GL_APIENTRY glDepthMask (GLboolean flag); +GL_APICALL void GL_APIENTRY glDepthRangef (GLfloat n, GLfloat f); +GL_APICALL void GL_APIENTRY glDetachShader (GLuint program, GLuint shader); +GL_APICALL void GL_APIENTRY glDisable (GLenum cap); +GL_APICALL void GL_APIENTRY glDisableVertexAttribArray (GLuint index); +GL_APICALL void GL_APIENTRY glDrawArrays (GLenum mode, GLint first, GLsizei count); +GL_APICALL void GL_APIENTRY glDrawElements (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices); +GL_APICALL void GL_APIENTRY glEnable (GLenum cap); +GL_APICALL void GL_APIENTRY glEnableVertexAttribArray (GLuint index); +GL_APICALL void GL_APIENTRY glFinish (void); +GL_APICALL void GL_APIENTRY glFlush (void); +GL_APICALL void GL_APIENTRY glFramebufferRenderbuffer (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer); +GL_APICALL void GL_APIENTRY glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); +GL_APICALL void GL_APIENTRY glFrontFace (GLenum mode); +GL_APICALL void GL_APIENTRY glGenBuffers (GLsizei n, GLuint* buffers); +GL_APICALL void GL_APIENTRY glGenerateMipmap (GLenum target); +GL_APICALL void GL_APIENTRY glGenFramebuffers (GLsizei n, GLuint* framebuffers); +GL_APICALL void GL_APIENTRY glGenRenderbuffers (GLsizei n, GLuint* renderbuffers); +GL_APICALL void GL_APIENTRY glGenTextures (GLsizei n, GLuint* textures); +GL_APICALL void GL_APIENTRY glGetActiveAttrib (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +GL_APICALL void GL_APIENTRY glGetActiveUniform (GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name); +GL_APICALL void GL_APIENTRY glGetAttachedShaders (GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders); +GL_APICALL GLint GL_APIENTRY glGetAttribLocation (GLuint program, const GLchar* name); +GL_APICALL void GL_APIENTRY glGetBooleanv (GLenum pname, GLboolean* params); +GL_APICALL void GL_APIENTRY glGetBufferParameteriv (GLenum target, GLenum pname, GLint* params); +GL_APICALL GLenum GL_APIENTRY glGetError (void); +GL_APICALL void GL_APIENTRY glGetFloatv (GLenum pname, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetFramebufferAttachmentParameteriv (GLenum target, GLenum attachment, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetIntegerv (GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetProgramiv (GLuint program, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetProgramInfoLog (GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog); +GL_APICALL void GL_APIENTRY glGetRenderbufferParameteriv (GLenum target, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetShaderiv (GLuint shader, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetShaderInfoLog (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog); +GL_APICALL void GL_APIENTRY glGetShaderPrecisionFormat (GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision); +GL_APICALL void GL_APIENTRY glGetShaderSource (GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source); +GL_APICALL const GLubyte* GL_APIENTRY glGetString (GLenum name); +GL_APICALL void GL_APIENTRY glGetTexParameterfv (GLenum target, GLenum pname, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetTexParameteriv (GLenum target, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetUniformfv (GLuint program, GLint location, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetUniformiv (GLuint program, GLint location, GLint* params); +GL_APICALL GLint GL_APIENTRY glGetUniformLocation (GLuint program, const GLchar* name); +GL_APICALL void GL_APIENTRY glGetVertexAttribfv (GLuint index, GLenum pname, GLfloat* params); +GL_APICALL void GL_APIENTRY glGetVertexAttribiv (GLuint index, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetVertexAttribPointerv (GLuint index, GLenum pname, GLvoid** pointer); +GL_APICALL void GL_APIENTRY glHint (GLenum target, GLenum mode); +GL_APICALL GLboolean GL_APIENTRY glIsBuffer (GLuint buffer); +GL_APICALL GLboolean GL_APIENTRY glIsEnabled (GLenum cap); +GL_APICALL GLboolean GL_APIENTRY glIsFramebuffer (GLuint framebuffer); +GL_APICALL GLboolean GL_APIENTRY glIsProgram (GLuint program); +GL_APICALL GLboolean GL_APIENTRY glIsRenderbuffer (GLuint renderbuffer); +GL_APICALL GLboolean GL_APIENTRY glIsShader (GLuint shader); +GL_APICALL GLboolean GL_APIENTRY glIsTexture (GLuint texture); +GL_APICALL void GL_APIENTRY glLineWidth (GLfloat width); +GL_APICALL void GL_APIENTRY glLinkProgram (GLuint program); +GL_APICALL void GL_APIENTRY glPixelStorei (GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glPolygonOffset (GLfloat factor, GLfloat units); +GL_APICALL void GL_APIENTRY glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels); +GL_APICALL void GL_APIENTRY glReleaseShaderCompiler (void); +GL_APICALL void GL_APIENTRY glRenderbufferStorage (GLenum target, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glSampleCoverage (GLfloat value, GLboolean invert); +GL_APICALL void GL_APIENTRY glScissor (GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glShaderBinary (GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length); +GL_APICALL void GL_APIENTRY glShaderSource (GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length); +GL_APICALL void GL_APIENTRY glStencilFunc (GLenum func, GLint ref, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilFuncSeparate (GLenum face, GLenum func, GLint ref, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilMask (GLuint mask); +GL_APICALL void GL_APIENTRY glStencilMaskSeparate (GLenum face, GLuint mask); +GL_APICALL void GL_APIENTRY glStencilOp (GLenum fail, GLenum zfail, GLenum zpass); +GL_APICALL void GL_APIENTRY glStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass); +GL_APICALL void GL_APIENTRY glTexImage2D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +GL_APICALL void GL_APIENTRY glTexParameterf (GLenum target, GLenum pname, GLfloat param); +GL_APICALL void GL_APIENTRY glTexParameterfv (GLenum target, GLenum pname, const GLfloat* params); +GL_APICALL void GL_APIENTRY glTexParameteri (GLenum target, GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glTexParameteriv (GLenum target, GLenum pname, const GLint* params); +GL_APICALL void GL_APIENTRY glTexSubImage2D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels); +GL_APICALL void GL_APIENTRY glUniform1f (GLint location, GLfloat x); +GL_APICALL void GL_APIENTRY glUniform1fv (GLint location, GLsizei count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform1i (GLint location, GLint x); +GL_APICALL void GL_APIENTRY glUniform1iv (GLint location, GLsizei count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniform2f (GLint location, GLfloat x, GLfloat y); +GL_APICALL void GL_APIENTRY glUniform2fv (GLint location, GLsizei count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform2i (GLint location, GLint x, GLint y); +GL_APICALL void GL_APIENTRY glUniform2iv (GLint location, GLsizei count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniform3f (GLint location, GLfloat x, GLfloat y, GLfloat z); +GL_APICALL void GL_APIENTRY glUniform3fv (GLint location, GLsizei count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform3i (GLint location, GLint x, GLint y, GLint z); +GL_APICALL void GL_APIENTRY glUniform3iv (GLint location, GLsizei count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniform4f (GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GL_APICALL void GL_APIENTRY glUniform4fv (GLint location, GLsizei count, const GLfloat* v); +GL_APICALL void GL_APIENTRY glUniform4i (GLint location, GLint x, GLint y, GLint z, GLint w); +GL_APICALL void GL_APIENTRY glUniform4iv (GLint location, GLsizei count, const GLint* v); +GL_APICALL void GL_APIENTRY glUniformMatrix2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUseProgram (GLuint program); +GL_APICALL void GL_APIENTRY glValidateProgram (GLuint program); +GL_APICALL void GL_APIENTRY glVertexAttrib1f (GLuint indx, GLfloat x); +GL_APICALL void GL_APIENTRY glVertexAttrib1fv (GLuint indx, const GLfloat* values); +GL_APICALL void GL_APIENTRY glVertexAttrib2f (GLuint indx, GLfloat x, GLfloat y); +GL_APICALL void GL_APIENTRY glVertexAttrib2fv (GLuint indx, const GLfloat* values); +GL_APICALL void GL_APIENTRY glVertexAttrib3f (GLuint indx, GLfloat x, GLfloat y, GLfloat z); +GL_APICALL void GL_APIENTRY glVertexAttrib3fv (GLuint indx, const GLfloat* values); +GL_APICALL void GL_APIENTRY glVertexAttrib4f (GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w); +GL_APICALL void GL_APIENTRY glVertexAttrib4fv (GLuint indx, const GLfloat* values); +GL_APICALL void GL_APIENTRY glVertexAttribPointer (GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr); +GL_APICALL void GL_APIENTRY glViewport (GLint x, GLint y, GLsizei width, GLsizei height); + +/* OpenGL ES 3.0 */ + +GL_APICALL void GL_APIENTRY glReadBuffer (GLenum mode); +GL_APICALL void GL_APIENTRY glDrawRangeElements (GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices); +GL_APICALL void GL_APIENTRY glTexImage3D (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels); +GL_APICALL void GL_APIENTRY glTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels); +GL_APICALL void GL_APIENTRY glCopyTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glCompressedTexImage3D (GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data); +GL_APICALL void GL_APIENTRY glCompressedTexSubImage3D (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data); +GL_APICALL void GL_APIENTRY glGenQueries (GLsizei n, GLuint* ids); +GL_APICALL void GL_APIENTRY glDeleteQueries (GLsizei n, const GLuint* ids); +GL_APICALL GLboolean GL_APIENTRY glIsQuery (GLuint id); +GL_APICALL void GL_APIENTRY glBeginQuery (GLenum target, GLuint id); +GL_APICALL void GL_APIENTRY glEndQuery (GLenum target); +GL_APICALL void GL_APIENTRY glGetQueryiv (GLenum target, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetQueryObjectuiv (GLuint id, GLenum pname, GLuint* params); +GL_APICALL GLboolean GL_APIENTRY glUnmapBuffer (GLenum target); +GL_APICALL void GL_APIENTRY glGetBufferPointerv (GLenum target, GLenum pname, GLvoid** params); +GL_APICALL void GL_APIENTRY glDrawBuffers (GLsizei n, const GLenum* bufs); +GL_APICALL void GL_APIENTRY glUniformMatrix2x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix3x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix2x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix4x2fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix3x4fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glUniformMatrix4x3fv (GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); +GL_APICALL void GL_APIENTRY glBlitFramebuffer (GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter); +GL_APICALL void GL_APIENTRY glRenderbufferStorageMultisample (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glFramebufferTextureLayer (GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer); +GL_APICALL GLvoid* GL_APIENTRY glMapBufferRange (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); +GL_APICALL void GL_APIENTRY glFlushMappedBufferRange (GLenum target, GLintptr offset, GLsizeiptr length); +GL_APICALL void GL_APIENTRY glBindVertexArray (GLuint array); +GL_APICALL void GL_APIENTRY glDeleteVertexArrays (GLsizei n, const GLuint* arrays); +GL_APICALL void GL_APIENTRY glGenVertexArrays (GLsizei n, GLuint* arrays); +GL_APICALL GLboolean GL_APIENTRY glIsVertexArray (GLuint array); +GL_APICALL void GL_APIENTRY glGetIntegeri_v (GLenum target, GLuint index, GLint* data); +GL_APICALL void GL_APIENTRY glBeginTransformFeedback (GLenum primitiveMode); +GL_APICALL void GL_APIENTRY glEndTransformFeedback (void); +GL_APICALL void GL_APIENTRY glBindBufferRange (GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size); +GL_APICALL void GL_APIENTRY glBindBufferBase (GLenum target, GLuint index, GLuint buffer); +GL_APICALL void GL_APIENTRY glTransformFeedbackVaryings (GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode); +GL_APICALL void GL_APIENTRY glGetTransformFeedbackVarying (GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name); +GL_APICALL void GL_APIENTRY glVertexAttribIPointer (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer); +GL_APICALL void GL_APIENTRY glGetVertexAttribIiv (GLuint index, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetVertexAttribIuiv (GLuint index, GLenum pname, GLuint* params); +GL_APICALL void GL_APIENTRY glVertexAttribI4i (GLuint index, GLint x, GLint y, GLint z, GLint w); +GL_APICALL void GL_APIENTRY glVertexAttribI4ui (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); +GL_APICALL void GL_APIENTRY glVertexAttribI4iv (GLuint index, const GLint* v); +GL_APICALL void GL_APIENTRY glVertexAttribI4uiv (GLuint index, const GLuint* v); +GL_APICALL void GL_APIENTRY glGetUniformuiv (GLuint program, GLint location, GLuint* params); +GL_APICALL GLint GL_APIENTRY glGetFragDataLocation (GLuint program, const GLchar *name); +GL_APICALL void GL_APIENTRY glUniform1ui (GLint location, GLuint v0); +GL_APICALL void GL_APIENTRY glUniform2ui (GLint location, GLuint v0, GLuint v1); +GL_APICALL void GL_APIENTRY glUniform3ui (GLint location, GLuint v0, GLuint v1, GLuint v2); +GL_APICALL void GL_APIENTRY glUniform4ui (GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3); +GL_APICALL void GL_APIENTRY glUniform1uiv (GLint location, GLsizei count, const GLuint* value); +GL_APICALL void GL_APIENTRY glUniform2uiv (GLint location, GLsizei count, const GLuint* value); +GL_APICALL void GL_APIENTRY glUniform3uiv (GLint location, GLsizei count, const GLuint* value); +GL_APICALL void GL_APIENTRY glUniform4uiv (GLint location, GLsizei count, const GLuint* value); +GL_APICALL void GL_APIENTRY glClearBufferiv (GLenum buffer, GLint drawbuffer, const GLint* value); +GL_APICALL void GL_APIENTRY glClearBufferuiv (GLenum buffer, GLint drawbuffer, const GLuint* value); +GL_APICALL void GL_APIENTRY glClearBufferfv (GLenum buffer, GLint drawbuffer, const GLfloat* value); +GL_APICALL void GL_APIENTRY glClearBufferfi (GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil); +GL_APICALL const GLubyte* GL_APIENTRY glGetStringi (GLenum name, GLuint index); +GL_APICALL void GL_APIENTRY glCopyBufferSubData (GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size); +GL_APICALL void GL_APIENTRY glGetUniformIndices (GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices); +GL_APICALL void GL_APIENTRY glGetActiveUniformsiv (GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params); +GL_APICALL GLuint GL_APIENTRY glGetUniformBlockIndex (GLuint program, const GLchar* uniformBlockName); +GL_APICALL void GL_APIENTRY glGetActiveUniformBlockiv (GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetActiveUniformBlockName (GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName); +GL_APICALL void GL_APIENTRY glUniformBlockBinding (GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); +GL_APICALL void GL_APIENTRY glDrawArraysInstanced (GLenum mode, GLint first, GLsizei count, GLsizei instanceCount); +GL_APICALL void GL_APIENTRY glDrawElementsInstanced (GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount); +GL_APICALL GLsync GL_APIENTRY glFenceSync (GLenum condition, GLbitfield flags); +GL_APICALL GLboolean GL_APIENTRY glIsSync (GLsync sync); +GL_APICALL void GL_APIENTRY glDeleteSync (GLsync sync); +GL_APICALL GLenum GL_APIENTRY glClientWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); +GL_APICALL void GL_APIENTRY glWaitSync (GLsync sync, GLbitfield flags, GLuint64 timeout); +GL_APICALL void GL_APIENTRY glGetInteger64v (GLenum pname, GLint64* params); +GL_APICALL void GL_APIENTRY glGetSynciv (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values); +GL_APICALL void GL_APIENTRY glGetInteger64i_v (GLenum target, GLuint index, GLint64* data); +GL_APICALL void GL_APIENTRY glGetBufferParameteri64v (GLenum target, GLenum pname, GLint64* params); +GL_APICALL void GL_APIENTRY glGenSamplers (GLsizei count, GLuint* samplers); +GL_APICALL void GL_APIENTRY glDeleteSamplers (GLsizei count, const GLuint* samplers); +GL_APICALL GLboolean GL_APIENTRY glIsSampler (GLuint sampler); +GL_APICALL void GL_APIENTRY glBindSampler (GLuint unit, GLuint sampler); +GL_APICALL void GL_APIENTRY glSamplerParameteri (GLuint sampler, GLenum pname, GLint param); +GL_APICALL void GL_APIENTRY glSamplerParameteriv (GLuint sampler, GLenum pname, const GLint* param); +GL_APICALL void GL_APIENTRY glSamplerParameterf (GLuint sampler, GLenum pname, GLfloat param); +GL_APICALL void GL_APIENTRY glSamplerParameterfv (GLuint sampler, GLenum pname, const GLfloat* param); +GL_APICALL void GL_APIENTRY glGetSamplerParameteriv (GLuint sampler, GLenum pname, GLint* params); +GL_APICALL void GL_APIENTRY glGetSamplerParameterfv (GLuint sampler, GLenum pname, GLfloat* params); +GL_APICALL void GL_APIENTRY glVertexAttribDivisor (GLuint index, GLuint divisor); +GL_APICALL void GL_APIENTRY glBindTransformFeedback (GLenum target, GLuint id); +GL_APICALL void GL_APIENTRY glDeleteTransformFeedbacks (GLsizei n, const GLuint* ids); +GL_APICALL void GL_APIENTRY glGenTransformFeedbacks (GLsizei n, GLuint* ids); +GL_APICALL GLboolean GL_APIENTRY glIsTransformFeedback (GLuint id); +GL_APICALL void GL_APIENTRY glPauseTransformFeedback (void); +GL_APICALL void GL_APIENTRY glResumeTransformFeedback (void); +GL_APICALL void GL_APIENTRY glGetProgramBinary (GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary); +GL_APICALL void GL_APIENTRY glProgramBinary (GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length); +GL_APICALL void GL_APIENTRY glProgramParameteri (GLuint program, GLenum pname, GLint value); +GL_APICALL void GL_APIENTRY glInvalidateFramebuffer (GLenum target, GLsizei numAttachments, const GLenum* attachments); +GL_APICALL void GL_APIENTRY glInvalidateSubFramebuffer (GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glTexStorage2D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height); +GL_APICALL void GL_APIENTRY glTexStorage3D (GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); +GL_APICALL void GL_APIENTRY glGetInternalformativ (GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/3rdparty/angle/include/GLES3/gl3ext.h b/src/3rdparty/angle/include/GLES3/gl3ext.h new file mode 100644 index 0000000000..4d4ea96c4d --- /dev/null +++ b/src/3rdparty/angle/include/GLES3/gl3ext.h @@ -0,0 +1,24 @@ +#ifndef __gl3ext_h_ +#define __gl3ext_h_ + +/* $Revision: 17809 $ on $Date:: 2012-05-14 08:03:36 -0700 #$ */ + +/* + * This document is licensed under the SGI Free Software B License Version + * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . + */ + +/* OpenGL ES 3 Extensions + * + * After an OES extension's interactions with OpenGl ES 3.0 have been documented, + * its tokens and function definitions should be added to this file in a manner + * that does not conflict with gl2ext.h or gl3.h. + * + * Tokens and function definitions for extensions that have become standard + * features in OpenGL ES 3.0 will not be added to this file. + * + * Applications using OpenGL-ES-2-only extensions should include gl2ext.h + */ + +#endif /* __gl3ext_h_ */ + diff --git a/src/3rdparty/angle/include/GLES3/gl3platform.h b/src/3rdparty/angle/include/GLES3/gl3platform.h new file mode 100644 index 0000000000..1bd1a850fa --- /dev/null +++ b/src/3rdparty/angle/include/GLES3/gl3platform.h @@ -0,0 +1,30 @@ +#ifndef __gl3platform_h_ +#define __gl3platform_h_ + +/* $Revision: 18437 $ on $Date:: 2012-07-08 23:31:39 -0700 #$ */ + +/* + * This document is licensed under the SGI Free Software B License Version + * 2.0. For details, see http://oss.sgi.com/projects/FreeB/ . + */ + +/* Platform-specific types and definitions for OpenGL ES 3.X gl3.h + * + * Adopters may modify khrplatform.h and this file to suit their platform. + * You are encouraged to submit all modifications to the Khronos group so that + * they can be included in future versions of this file. Please submit changes + * by sending them to the public Khronos Bugzilla (http://khronos.org/bugzilla) + * by filing a bug against product "OpenGL-ES" component "Registry". + */ + +#include + +#ifndef GL_APICALL +#define GL_APICALL KHRONOS_APICALL +#endif + +#ifndef GL_APIENTRY +#define GL_APIENTRY KHRONOS_APIENTRY +#endif + +#endif /* __gl3platform_h_ */ diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h index 9912939b95..4b69fb1fb0 100644 --- a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h +++ b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h @@ -31,24 +31,19 @@ // and the shading language compiler. // +namespace sh +{ +// GLenum alias +typedef unsigned int GLenum; +} + #ifdef __cplusplus extern "C" { #endif // Version number for shader translation API. -// It is incremented everytime the API changes. -#define ANGLE_SH_VERSION 112 - -// -// The names of the following enums have been derived by replacing GL prefix -// with SH. For example, SH_INFO_LOG_LENGTH is equivalent to GL_INFO_LOG_LENGTH. -// The enum values are also equal to the values of their GL counterpart. This -// is done to make it easier for applications to use the shader library. -// -typedef enum { - SH_FRAGMENT_SHADER = 0x8B30, - SH_VERTEX_SHADER = 0x8B31 -} ShShaderType; +// It is incremented every time the API changes. +#define ANGLE_SH_VERSION 128 typedef enum { SH_GLES2_SPEC = 0x8B40, @@ -85,29 +80,6 @@ typedef enum { SH_HLSL11_OUTPUT = 0x8B48 } ShShaderOutput; -typedef enum { - SH_NONE = 0, - SH_INT = 0x1404, - SH_FLOAT = 0x1406, - SH_FLOAT_VEC2 = 0x8B50, - SH_FLOAT_VEC3 = 0x8B51, - SH_FLOAT_VEC4 = 0x8B52, - SH_INT_VEC2 = 0x8B53, - SH_INT_VEC3 = 0x8B54, - SH_INT_VEC4 = 0x8B55, - SH_BOOL = 0x8B56, - SH_BOOL_VEC2 = 0x8B57, - SH_BOOL_VEC3 = 0x8B58, - SH_BOOL_VEC4 = 0x8B59, - SH_FLOAT_MAT2 = 0x8B5A, - SH_FLOAT_MAT3 = 0x8B5B, - SH_FLOAT_MAT4 = 0x8B5C, - SH_SAMPLER_2D = 0x8B5E, - SH_SAMPLER_CUBE = 0x8B60, - SH_SAMPLER_2D_RECT_ARB = 0x8B63, - SH_SAMPLER_EXTERNAL_OES = 0x8D66 -} ShDataType; - typedef enum { SH_PRECISION_HIGHP = 0x5001, SH_PRECISION_MEDIUMP = 0x5002, @@ -116,19 +88,26 @@ typedef enum { } ShPrecisionType; typedef enum { - SH_INFO_LOG_LENGTH = 0x8B84, - SH_OBJECT_CODE_LENGTH = 0x8B88, // GL_SHADER_SOURCE_LENGTH - SH_ACTIVE_UNIFORMS = 0x8B86, - SH_ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87, - SH_ACTIVE_ATTRIBUTES = 0x8B89, - SH_ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A, - SH_VARYINGS = 0x8BBB, - SH_VARYING_MAX_LENGTH = 0x8BBC, - SH_MAPPED_NAME_MAX_LENGTH = 0x6000, - SH_NAME_MAX_LENGTH = 0x6001, - SH_HASHED_NAME_MAX_LENGTH = 0x6002, - SH_HASHED_NAMES_COUNT = 0x6003, - SH_ACTIVE_UNIFORMS_ARRAY = 0x6004 + SH_INFO_LOG_LENGTH = 0x8B84, + SH_OBJECT_CODE_LENGTH = 0x8B88, // GL_SHADER_SOURCE_LENGTH + SH_ACTIVE_UNIFORMS = 0x8B86, + SH_ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87, + SH_ACTIVE_ATTRIBUTES = 0x8B89, + SH_ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A, + SH_VARYINGS = 0x8BBB, + SH_VARYING_MAX_LENGTH = 0x8BBC, + SH_MAPPED_NAME_MAX_LENGTH = 0x6000, + SH_NAME_MAX_LENGTH = 0x6001, + SH_HASHED_NAME_MAX_LENGTH = 0x6002, + SH_HASHED_NAMES_COUNT = 0x6003, + SH_ACTIVE_UNIFORMS_ARRAY = 0x6004, + SH_SHADER_VERSION = 0x6005, + SH_ACTIVE_INTERFACE_BLOCKS_ARRAY = 0x6006, + SH_ACTIVE_OUTPUT_VARIABLES_ARRAY = 0x6007, + SH_ACTIVE_ATTRIBUTES_ARRAY = 0x6008, + SH_ACTIVE_VARYINGS_ARRAY = 0x6009, + SH_RESOURCES_STRING_LENGTH = 0x600A, + SH_OUTPUT_TYPE = 0x600B } ShShaderInfo; // Compile options. @@ -140,13 +119,17 @@ typedef enum { SH_VARIABLES = 0x0008, SH_LINE_DIRECTIVES = 0x0010, SH_SOURCE_PATH = 0x0020, - SH_MAP_LONG_VARIABLE_NAMES = 0x0040, - SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX = 0x0080, + SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX = 0x0040, + // If a sampler array index happens to be a loop index, + // 1) if its type is integer, unroll the loop. + // 2) if its type is float, fail the shader compile. + // This is to work around a mac driver bug. + SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX = 0x0080, // This is needed only as a workaround for certain OpenGL driver bugs. SH_EMULATE_BUILT_IN_FUNCTIONS = 0x0100, - // This is an experimental flag to enforce restrictions that aim to prevent + // This is an experimental flag to enforce restrictions that aim to prevent // timing attacks. // It generates compilation errors for shaders that could expose sensitive // texture information via the timing channel. @@ -159,7 +142,7 @@ typedef enum { // This flag only has an effect if all of the following are true: // - The shader spec is SH_WEBGL_SPEC. // - The compile options contain the SH_TIMING_RESTRICTIONS flag. - // - The shader type is SH_FRAGMENT_SHADER. + // - The shader type is GL_FRAGMENT_SHADER. SH_DEPENDENCY_GRAPH = 0x0400, // Enforce the GLSL 1.017 Appendix A section 7 packing restrictions. @@ -202,6 +185,10 @@ typedef enum { // It is intended as a workaround for drivers which incorrectly optimize // out such varyings and cause a link failure. SH_INIT_VARYINGS_WITHOUT_STATIC_USE = 0x20000, + + // This flag scalarizes vec/ivec/bvec/mat constructor args. + // It is intended as a workaround for Linux/Mac driver bugs. + SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS = 0x40000, } ShCompileOptions; // Defines alternate strategies for implementing array index clamping. @@ -252,11 +239,18 @@ typedef struct int ARB_texture_rectangle; int EXT_draw_buffers; int EXT_frag_depth; + int EXT_shader_texture_lod; // Set to 1 if highp precision is supported in the fragment language. // Default is 0. int FragmentPrecisionHigh; + // GLSL ES 3.0 constants. + int MaxVertexOutputVectors; + int MaxFragmentInputVectors; + int MinProgramTexelOffset; + int MaxProgramTexelOffset; + // Name Hashing. // Set a 64 bit hash function to enable user-defined name hashing. // Default is NULL. @@ -280,27 +274,38 @@ COMPILER_EXPORT void ShInitBuiltInResources(ShBuiltInResources* resources); // // ShHandle held by but opaque to the driver. It is allocated, -// managed, and de-allocated by the compiler. It's contents +// managed, and de-allocated by the compiler. Its contents // are defined by and used by the compiler. // // If handle creation fails, 0 will be returned. // typedef void* ShHandle; +// +// Returns the a concatenated list of the items in ShBuiltInResources as a string. +// This function must be updated whenever ShBuiltInResources is changed. +// Parameters: +// handle: Specifies the handle of the compiler to be used. +// outStringLen: Specifies the size of the buffer, in number of characters. The size +// of the buffer required to store the resources string can be obtained +// by calling ShGetInfo with SH_RESOURCES_STRING_LENGTH. +// outStr: Returns a null-terminated string representing all the built-in resources. +COMPILER_EXPORT void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outStr); + // // Driver calls these to create and destroy compiler objects. // // Returns the handle of constructed compiler, null if the requested compiler is // not supported. // Parameters: -// type: Specifies the type of shader - SH_FRAGMENT_SHADER or SH_VERTEX_SHADER. +// type: Specifies the type of shader - GL_FRAGMENT_SHADER or GL_VERTEX_SHADER. // spec: Specifies the language spec the compiler must conform to - // SH_GLES2_SPEC or SH_WEBGL_SPEC. // output: Specifies the output code type - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT, // SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT. // resources: Specifies the built-in resources. COMPILER_EXPORT ShHandle ShConstructCompiler( - ShShaderType type, + sh::GLenum type, ShShaderSpec spec, ShShaderOutput output, const ShBuiltInResources* resources); @@ -364,6 +369,8 @@ COMPILER_EXPORT int ShCompile( // SH_HASHED_NAME_MAX_LENGTH: the max length of a hashed name including the // null termination character. // SH_HASHED_NAMES_COUNT: the number of hashed names from the latest compile. +// SH_SHADER_VERSION: the version of the shader language +// SH_OUTPUT_TYPE: the currently set language output type // // params: Requested parameter COMPILER_EXPORT void ShGetInfo(const ShHandle handle, @@ -422,7 +429,7 @@ COMPILER_EXPORT void ShGetVariableInfo(const ShHandle handle, int index, size_t* length, int* size, - ShDataType* type, + sh::GLenum* type, ShPrecisionType* precision, int* staticUse, char* name, @@ -460,7 +467,7 @@ COMPILER_EXPORT void ShGetInfoPointer(const ShHandle handle, typedef struct { - ShDataType type; + sh::GLenum type; int size; } ShVariableInfo; @@ -477,6 +484,29 @@ COMPILER_EXPORT int ShCheckVariablesWithinPackingLimits( ShVariableInfo* varInfoArray, size_t varInfoArraySize); +// Gives the compiler-assigned register for an interface block. +// The method writes the value to the output variable "indexOut". +// Returns true if it found a valid interface block, false otherwise. +// Parameters: +// handle: Specifies the compiler +// interfaceBlockName: Specifies the interface block +// indexOut: output variable that stores the assigned register +COMPILER_EXPORT bool ShGetInterfaceBlockRegister(const ShHandle handle, + const char *interfaceBlockName, + unsigned int *indexOut); + +// Gives the compiler-assigned register for uniforms in the default +// interface block. +// The method writes the value to the output variable "indexOut". +// Returns true if it found a valid default uniform, false otherwise. +// Parameters: +// handle: Specifies the compiler +// interfaceBlockName: Specifies the uniform +// indexOut: output variable that stores the assigned register +COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle, + const char *uniformName, + unsigned int *indexOut); + #ifdef __cplusplus } #endif diff --git a/src/3rdparty/angle/include/angle_gl.h b/src/3rdparty/angle/include/angle_gl.h new file mode 100644 index 0000000000..663aa259ea --- /dev/null +++ b/src/3rdparty/angle/include/angle_gl.h @@ -0,0 +1,26 @@ +// +// 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. +// +// angle_gl.h: +// Includes all necessary GL headers and definitions for ANGLE. +// + +#ifndef ANGLE_GL_H_ +#define ANGLE_GL_H_ + +#define GL_GLEXT_PROTOTYPES +#define GL_APICALL + +#include "GLES2/gl2.h" +#include "GLES2/gl2ext.h" +#include "GLES3/gl3.h" +#include "GLES3/gl3ext.h" + +// The following enum is used in ANGLE, but is from desktop GL +#ifndef GL_SAMPLER_2D_RECT_ARB +#define GL_SAMPLER_2D_RECT_ARB 0x8B63 +#endif + +#endif // ANGLE_GL_H_ diff --git a/src/3rdparty/angle/src/commit.h b/src/3rdparty/angle/src/commit.h index f4a36a3cfe..e1378309a4 100644 --- a/src/3rdparty/angle/src/commit.h +++ b/src/3rdparty/angle/src/commit.h @@ -1,2 +1,12 @@ -#define ANGLE_COMMIT_HASH "5bb7ec572d0a" +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// commit.h: +// This is a default commit hash header, when git is not available. +// + +#define ANGLE_COMMIT_HASH "07d49ef5350a" #define ANGLE_COMMIT_HASH_SIZE 12 +#define ANGLE_COMMIT_DATE "2014-07-25 16:01:42 +0000" diff --git a/src/3rdparty/angle/src/common/RefCountObject.h b/src/3rdparty/angle/src/common/RefCountObject.h index 727c71c362..8635aa59d8 100644 --- a/src/3rdparty/angle/src/common/RefCountObject.h +++ b/src/3rdparty/angle/src/common/RefCountObject.h @@ -14,8 +14,7 @@ #include -#define GL_APICALL -#include +#include "angle_gl.h" #include "common/debug.h" @@ -47,7 +46,7 @@ class RefCountObjectBindingPointer public: GLuint id() const { return (mObject != NULL) ? mObject->id() : 0; } - bool operator ! () const { return (get() == NULL); } + bool operator!() const { return (get() == NULL); } private: RefCountObject *mObject; @@ -59,7 +58,38 @@ class BindingPointer : public RefCountObjectBindingPointer public: void set(ObjectType *newObject) { RefCountObjectBindingPointer::set(newObject); } ObjectType *get() const { return static_cast(RefCountObjectBindingPointer::get()); } - ObjectType *operator -> () const { return get(); } + ObjectType *operator->() const { return get(); } +}; + +template +class OffsetBindingPointer : public RefCountObjectBindingPointer +{ + public: + OffsetBindingPointer() : mOffset(0), mSize(0) { } + + void set(ObjectType *newObject) + { + RefCountObjectBindingPointer::set(newObject); + mOffset = 0; + mSize = 0; + } + + void set(ObjectType *newObject, GLintptr offset, GLsizeiptr size) + { + RefCountObjectBindingPointer::set(newObject); + mOffset = offset; + mSize = size; + } + + GLintptr getOffset() const { return mOffset; } + GLsizeiptr getSize() const { return mSize; } + + ObjectType *get() const { return static_cast(RefCountObjectBindingPointer::get()); } + ObjectType *operator->() const { return get(); } + + private: + GLintptr mOffset; + GLsizeiptr mSize; }; #endif // COMMON_REFCOUNTOBJECT_H_ diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h index 3d4246f55c..d94b4f5ff9 100644 --- a/src/3rdparty/angle/src/common/angleutils.h +++ b/src/3rdparty/angle/src/common/angleutils.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 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. // @@ -9,7 +9,13 @@ #ifndef COMMON_ANGLEUTILS_H_ #define COMMON_ANGLEUTILS_H_ +#include "common/platform.h" + #include +#include +#include +#include +#include // A macro to disallow the copy constructor and operator= functions // This must be used in the private: declarations for a class @@ -49,6 +55,16 @@ void SafeDelete(T*& resource) resource = NULL; } +template +void SafeDeleteContainer(T& resource) +{ + for (typename T::iterator i = resource.begin(); i != resource.end(); i++) + { + SafeDelete(*i); + } + resource.clear(); +} + template void SafeDeleteArray(T*& resource) { @@ -56,6 +72,65 @@ void SafeDeleteArray(T*& resource) resource = NULL; } +// Provide a less-than function for comparing structs +// Note: struct memory must be initialized to zero, because of packing gaps +template +inline bool StructLessThan(const T &a, const T &b) +{ + return (memcmp(&a, &b, sizeof(T)) < 0); +} + +// Provide a less-than function for comparing structs +// Note: struct memory must be initialized to zero, because of packing gaps +template +inline bool StructEquals(const T &a, const T &b) +{ + return (memcmp(&a, &b, sizeof(T)) == 0); +} + +template +inline void StructZero(T *obj) +{ + memset(obj, 0, sizeof(T)); +} + +inline const char* MakeStaticString(const std::string &str) +{ + static std::set strings; + std::set::iterator it = strings.find(str); + if (it != strings.end()) + { + return it->c_str(); + } + + return strings.insert(str).first->c_str(); +} + +inline std::string ArrayString(unsigned int i) +{ + // We assume UINT_MAX and GL_INVALID_INDEX are equal + // See DynamicHLSL.cpp + if (i == UINT_MAX) + { + return ""; + } + + std::stringstream strstr; + + strstr << "["; + strstr << i; + strstr << "]"; + + return strstr.str(); +} + +inline std::string Str(int i) +{ + std::stringstream strstr; + strstr << i; + return strstr.str(); +} + #if defined(_MSC_VER) && _MSC_VER < 1900 #define snprintf _snprintf #endif @@ -66,5 +141,7 @@ void SafeDeleteArray(T*& resource) #define GL_BGRA4_ANGLEX 0x6ABC #define GL_BGR5_A1_ANGLEX 0x6ABD +#define GL_INT_64_ANGLEX 0x6ABE +#define GL_STRUCT_ANGLEX 0x6ABF #endif // COMMON_ANGLEUTILS_H_ diff --git a/src/3rdparty/angle/src/common/blocklayout.cpp b/src/3rdparty/angle/src/common/blocklayout.cpp new file mode 100644 index 0000000000..7db6e980f1 --- /dev/null +++ b/src/3rdparty/angle/src/common/blocklayout.cpp @@ -0,0 +1,289 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// blocklayout.cpp: +// Implementation for block layout classes and methods. +// + +#include "common/blocklayout.h" +#include "common/shadervars.h" +#include "common/mathutil.h" +#include "common/utilities.h" + +namespace sh +{ + +BlockLayoutEncoder::BlockLayoutEncoder() + : mCurrentOffset(0) +{ +} + +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) +{ + int arrayStride; + int matrixStride; + + getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride); + + const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix); + + advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride); +} + +void BlockLayoutEncoder::nextRegister() +{ + mCurrentOffset = rx::roundUp(mCurrentOffset, ComponentsPerRegister); +} + +Std140BlockEncoder::Std140BlockEncoder() +{ +} + +void Std140BlockEncoder::enterAggregateType() +{ + nextRegister(); +} + +void Std140BlockEncoder::exitAggregateType() +{ + nextRegister(); +} + +void Std140BlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) +{ + // We assume we are only dealing with 4 byte components (no doubles or half-words currently) + ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent); + + size_t baseAlignment = 0; + int matrixStride = 0; + int arrayStride = 0; + + if (gl::IsMatrixType(type)) + { + baseAlignment = ComponentsPerRegister; + matrixStride = ComponentsPerRegister; + + if (arraySize > 0) + { + const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); + arrayStride = ComponentsPerRegister * numRegisters; + } + } + else if (arraySize > 0) + { + baseAlignment = ComponentsPerRegister; + arrayStride = ComponentsPerRegister; + } + else + { + const int numComponents = gl::VariableComponentCount(type); + baseAlignment = (numComponents == 3 ? 4u : static_cast(numComponents)); + } + + mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment); + + *matrixStrideOut = matrixStride; + *arrayStrideOut = arrayStride; +} + +void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) +{ + if (arraySize > 0) + { + mCurrentOffset += arrayStride * arraySize; + } + else if (gl::IsMatrixType(type)) + { + ASSERT(matrixStride == ComponentsPerRegister); + const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); + mCurrentOffset += ComponentsPerRegister * numRegisters; + } + else + { + mCurrentOffset += gl::VariableComponentCount(type); + } +} + +HLSLBlockEncoder::HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy) + : mEncoderStrategy(strategy) +{ +} + +void HLSLBlockEncoder::enterAggregateType() +{ + nextRegister(); +} + +void HLSLBlockEncoder::exitAggregateType() +{ +} + +void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) +{ + // We assume we are only dealing with 4 byte components (no doubles or half-words currently) + ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent); + + int matrixStride = 0; + int arrayStride = 0; + + // if variables are not to be packed, or we're about to + // pack a matrix or array, skip to the start of the next + // register + if (!isPacked() || + gl::IsMatrixType(type) || + arraySize > 0) + { + nextRegister(); + } + + if (gl::IsMatrixType(type)) + { + matrixStride = ComponentsPerRegister; + + if (arraySize > 0) + { + const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); + arrayStride = ComponentsPerRegister * numRegisters; + } + } + else if (arraySize > 0) + { + arrayStride = ComponentsPerRegister; + } + else if (isPacked()) + { + int numComponents = gl::VariableComponentCount(type); + if ((numComponents + (mCurrentOffset % ComponentsPerRegister)) > ComponentsPerRegister) + { + nextRegister(); + } + } + + *matrixStrideOut = matrixStride; + *arrayStrideOut = arrayStride; +} + +void HLSLBlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) +{ + if (arraySize > 0) + { + mCurrentOffset += arrayStride * (arraySize - 1); + } + + if (gl::IsMatrixType(type)) + { + ASSERT(matrixStride == ComponentsPerRegister); + const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix); + const int numComponents = gl::MatrixComponentCount(type, isRowMajorMatrix); + mCurrentOffset += ComponentsPerRegister * (numRegisters - 1); + mCurrentOffset += numComponents; + } + else if (isPacked()) + { + mCurrentOffset += gl::VariableComponentCount(type); + } + else + { + mCurrentOffset += ComponentsPerRegister; + } +} + +void HLSLBlockEncoder::skipRegisters(unsigned int numRegisters) +{ + mCurrentOffset += (numRegisters * ComponentsPerRegister); +} + +HLSLBlockEncoder::HLSLBlockEncoderStrategy HLSLBlockEncoder::GetStrategyFor(ShShaderOutput outputType) +{ + switch (outputType) + { + case SH_HLSL9_OUTPUT: return ENCODE_LOOSE; + case SH_HLSL11_OUTPUT: return ENCODE_PACKED; + default: UNREACHABLE(); return ENCODE_PACKED; + } +} + +template +void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *encoder) +{ + if (variable.isStruct()) + { + for (size_t arrayElement = 0; arrayElement < variable.elementCount(); arrayElement++) + { + encoder->enterAggregateType(); + + for (size_t fieldIndex = 0; fieldIndex < variable.fields.size(); fieldIndex++) + { + HLSLVariableRegisterCount(variable.fields[fieldIndex], encoder); + } + + encoder->exitAggregateType(); + } + } + else + { + // We operate only on varyings and uniforms, which do not have matrix layout qualifiers + encoder->encodeType(variable.type, variable.arraySize, false); + } +} + +unsigned int HLSLVariableRegisterCount(const Varying &variable) +{ + HLSLBlockEncoder encoder(HLSLBlockEncoder::ENCODE_PACKED); + HLSLVariableRegisterCount(variable, &encoder); + + const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister); + return static_cast(rx::roundUp(encoder.getBlockSize(), registerBytes) / registerBytes); +} + +unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType) +{ + HLSLBlockEncoder encoder(HLSLBlockEncoder::GetStrategyFor(outputType)); + HLSLVariableRegisterCount(variable, &encoder); + + const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister); + return static_cast(rx::roundUp(encoder.getBlockSize(), registerBytes) / registerBytes); +} + +} diff --git a/src/3rdparty/angle/src/common/blocklayout.h b/src/3rdparty/angle/src/common/blocklayout.h new file mode 100644 index 0000000000..3a1ab5ccb0 --- /dev/null +++ b/src/3rdparty/angle/src/common/blocklayout.h @@ -0,0 +1,128 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// blocklayout.h: +// Methods and classes related to uniform layout and packing in GLSL and HLSL. +// + +#ifndef COMMON_BLOCKLAYOUT_H_ +#define COMMON_BLOCKLAYOUT_H_ + +#include +#include "angle_gl.h" +#include +#include + +namespace sh +{ +struct ShaderVariable; +struct InterfaceBlockField; +struct Uniform; +struct Varying; +struct InterfaceBlock; + +struct BlockMemberInfo +{ + BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix) + : offset(offset), + arrayStride(arrayStride), + matrixStride(matrixStride), + isRowMajorMatrix(isRowMajorMatrix) + {} + + static BlockMemberInfo getDefaultBlockInfo() + { + return BlockMemberInfo(-1, -1, -1, false); + } + + int offset; + int arrayStride; + int matrixStride; + bool isRowMajorMatrix; +}; + +class BlockLayoutEncoder +{ + public: + BlockLayoutEncoder(); + + void encodeInterfaceBlockFields(const std::vector &fields); + BlockMemberInfo encodeInterfaceBlockField(const InterfaceBlockField &field); + void encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix); + + size_t getBlockSize() const { return mCurrentOffset * BytesPerComponent; } + size_t getCurrentRegister() const { return mCurrentOffset / ComponentsPerRegister; } + size_t getCurrentElement() const { return mCurrentOffset % ComponentsPerRegister; } + + virtual void enterAggregateType() = 0; + virtual void exitAggregateType() = 0; + + static const size_t BytesPerComponent = 4u; + static const unsigned int ComponentsPerRegister = 4u; + + protected: + size_t mCurrentOffset; + + void nextRegister(); + + virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut) = 0; + virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride) = 0; +}; + +// Block layout according to the std140 block layout +// See "Standard Uniform Block Layout" in Section 2.11.6 of the OpenGL ES 3.0 specification + +class Std140BlockEncoder : public BlockLayoutEncoder +{ + public: + Std140BlockEncoder(); + + virtual void enterAggregateType(); + virtual void exitAggregateType(); + + protected: + virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut); + virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride); +}; + +// Block layout packed according to the D3D9 or default D3D10+ register packing rules +// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx +// The strategy should be ENCODE_LOOSE for D3D9 constant blocks, and ENCODE_PACKED +// for everything else (D3D10+ constant blocks and all attributes/varyings). + +class HLSLBlockEncoder : public BlockLayoutEncoder +{ + public: + enum HLSLBlockEncoderStrategy + { + ENCODE_PACKED, + ENCODE_LOOSE + }; + + HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy); + + virtual void enterAggregateType(); + virtual void exitAggregateType(); + void skipRegisters(unsigned int numRegisters); + + bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; } + + static HLSLBlockEncoderStrategy GetStrategyFor(ShShaderOutput outputType); + + protected: + virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut); + virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride); + + HLSLBlockEncoderStrategy mEncoderStrategy; +}; + +// This method returns the number of used registers for a ShaderVariable. It is dependent on the HLSLBlockEncoder +// class to count the number of used registers in a struct (which are individually packed according to the same rules). +unsigned int HLSLVariableRegisterCount(const Varying &variable); +unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType); + +} + +#endif // COMMON_BLOCKLAYOUT_H_ diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp index 05d3dc62ad..d6eecf7157 100644 --- a/src/3rdparty/angle/src/common/debug.cpp +++ b/src/3rdparty/angle/src/common/debug.cpp @@ -7,11 +7,12 @@ // debug.cpp: Debugging utilities. #include "common/debug.h" -#include +#include "common/platform.h" -#if defined(ANGLE_ENABLE_PERF) -#include -#endif +#include +#include +#include +#include namespace gl { @@ -23,25 +24,38 @@ 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'; +#endif + #if defined(ANGLE_ENABLE_PERF) if (perfActive()) { - char message[32768]; - int len = vsprintf_s(message, format, vararg); - if (len < 0) + // The perf function only accepts wide strings, widen the ascii message + static std::wstring wideMessage; + if (wideMessage.capacity() < asciiMessageBuffer.size()) { - return; + wideMessage.reserve(asciiMessageBuffer.size()); } - // There are no ASCII variants of these D3DPERF functions. - wchar_t wideMessage[32768]; - for (int i = 0; i < len; ++i) - { - wideMessage[i] = message[i]; - } - wideMessage[len] = 0; + wideMessage.assign(asciiMessageBuffer.begin(), asciiMessageBuffer.begin() + len); - perfFunc(0, wideMessage); + perfFunc(0, wideMessage.c_str()); } #endif // ANGLE_ENABLE_PERF @@ -53,12 +67,13 @@ static void output(bool traceFileDebugOnly, PerfOutputFunction perfFunc, const c } #endif // NDEBUG - FILE* file = fopen(TRACE_OUTPUT_FILE, "a"); + static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app); if (file) { - vfprintf(file, format, vararg); - fclose(file); + file.write(&asciiMessageBuffer[0], len); + file.flush(); } + #endif // ANGLE_ENABLE_TRACE } diff --git a/src/3rdparty/angle/src/common/debug.h b/src/3rdparty/angle/src/common/debug.h index 793843895c..997ebca6be 100644 --- a/src/3rdparty/angle/src/common/debug.h +++ b/src/3rdparty/angle/src/common/debug.h @@ -62,7 +62,7 @@ namespace gl // A macro to log a performance event around a scope. #if defined(ANGLE_ENABLE_TRACE) || defined(ANGLE_ENABLE_PERF) #if defined(_MSC_VER) -#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__(__FUNCTION__ message "\n", __VA_ARGS__); +#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__); #else #define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper(message "\n", ##__VA_ARGS__); #endif // _MSC_VER @@ -77,15 +77,30 @@ namespace gl ERR("\t! Assert failed in %s(%d): "#expression"\n", __FUNCTION__, __LINE__); \ assert(expression); \ } while(0) +#define UNUSED_ASSERTION_VARIABLE(variable) #else #define ASSERT(expression) (void(0)) +#define UNUSED_ASSERTION_VARIABLE(variable) ((void)variable) +#endif + +#ifndef ANGLE_ENABLE_TRACE +#define UNUSED_TRACE_VARIABLE(variable) ((void)variable) +#else +#define UNUSED_TRACE_VARIABLE(variable) #endif // A macro to indicate unimplemented functionality + +// 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 +#define NOASSERT_UNIMPLEMENTED 0 +#endif + #if !defined(NDEBUG) #define UNIMPLEMENTED() do { \ FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__); \ - assert(false); \ + assert(NOASSERT_UNIMPLEMENTED); \ } while(0) #else #define UNIMPLEMENTED() FIXME("\t! Unimplemented: %s(%d)\n", __FUNCTION__, __LINE__) @@ -101,9 +116,7 @@ namespace gl #define UNREACHABLE() ERR("\t! Unreachable reached: %s(%d)\n", __FUNCTION__, __LINE__) #endif -// A macro that determines whether an object has a given runtime type. MSVC uses _CPPRTTI. -// GCC uses __GXX_RTTI, but the macro was introduced in version 4.3, so we assume that all older -// versions support RTTI. +// A macro that determines whether an object has a given runtime type. #if !defined(NDEBUG) && (!defined(_MSC_VER) || defined(_CPPRTTI)) && (!defined(__GNUC__) || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 3) || defined(__GXX_RTTI)) #define HAS_DYNAMIC_TYPE(type, obj) (dynamic_cast(obj) != NULL) #else @@ -111,6 +124,13 @@ namespace gl #endif // A macro functioning as a compile-time assert to validate constant conditions -#define META_ASSERT(condition) typedef int COMPILE_TIME_ASSERT_##__LINE__[static_cast(condition)?1:-1] +#if defined(_MSC_VER) && _MSC_VER >= 1600 +#define META_ASSERT_MSG(condition, msg) static_assert(condition, msg) +#else +#define META_ASSERT_CONCAT(a, b) a ## b +#define META_ASSERT_CONCAT2(a, b) META_ASSERT_CONCAT(a, b) +#define META_ASSERT_MSG(condition, msg) typedef int META_ASSERT_CONCAT2(COMPILE_TIME_ASSERT_, __LINE__)[static_cast(condition)?1:-1] +#endif +#define META_ASSERT(condition) META_ASSERT_MSG(condition, "compile time assertion failed.") #endif // COMMON_DEBUG_H_ diff --git a/src/3rdparty/angle/src/common/event_tracer.cpp b/src/3rdparty/angle/src/common/event_tracer.cpp index 142373d13f..353c69d05c 100644 --- a/src/3rdparty/angle/src/common/event_tracer.cpp +++ b/src/3rdparty/angle/src/common/event_tracer.cpp @@ -15,7 +15,7 @@ AddTraceEventFunc g_addTraceEvent; extern "C" { void TRACE_ENTRY SetTraceFunctionPointers(GetCategoryEnabledFlagFunc getCategoryEnabledFlag, - AddTraceEventFunc addTraceEvent) + AddTraceEventFunc addTraceEvent) { gl::g_getCategoryEnabledFlag = getCategoryEnabledFlag; gl::g_addTraceEvent = addTraceEvent; diff --git a/src/3rdparty/angle/src/common/event_tracer.h b/src/3rdparty/angle/src/common/event_tracer.h index 14b7b298fd..fa97435faa 100644 --- a/src/3rdparty/angle/src/common/event_tracer.h +++ b/src/3rdparty/angle/src/common/event_tracer.h @@ -5,12 +5,14 @@ #ifndef COMMON_EVENT_TRACER_H_ #define COMMON_EVENT_TRACER_H_ +#include "common/platform.h" + #if !defined(TRACE_ENTRY) -#if defined(_WIN32) -#define TRACE_ENTRY __stdcall -#else -#define TRACE_ENTRY -#endif // // _WIN32 +# ifdef ANGLE_PLATFORM_WINDOWS +# define TRACE_ENTRY __stdcall +# else +# define TRACE_ENTRY +# endif // ANGLE_PLATFORM_WINDOWS #endif //TRACE_ENTRY extern "C" { diff --git a/src/3rdparty/angle/src/common/mathutil.cpp b/src/3rdparty/angle/src/common/mathutil.cpp new file mode 100644 index 0000000000..20b3f0c113 --- /dev/null +++ b/src/3rdparty/angle/src/common/mathutil.cpp @@ -0,0 +1,66 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// mathutil.cpp: Math and bit manipulation functions. + +#include "common/mathutil.h" +#include +#include + +namespace gl +{ + +struct RGB9E5Data +{ + unsigned int R : 9; + unsigned int G : 9; + unsigned int B : 9; + unsigned int E : 5; +}; + +// B is the exponent bias (15) +static const int g_sharedexp_bias = 15; + +// N is the number of mantissa bits per component (9) +static const int g_sharedexp_mantissabits = 9; + +// Emax is the maximum allowed biased exponent value (31) +static const int g_sharedexp_maxexponent = 31; + +static const float g_sharedexp_max = ((pow(2.0f, g_sharedexp_mantissabits) - 1) / + pow(2.0f, g_sharedexp_mantissabits)) * + pow(2.0f, g_sharedexp_maxexponent - g_sharedexp_bias); + +unsigned int convertRGBFloatsTo999E5(float red, float green, float blue) +{ + const float red_c = std::max(0, std::min(g_sharedexp_max, red)); + const float green_c = std::max(0, std::min(g_sharedexp_max, green)); + const float blue_c = std::max(0, std::min(g_sharedexp_max, blue)); + + const float max_c = std::max(std::max(red_c, green_c), blue_c); + const float exp_p = std::max(-g_sharedexp_bias - 1, floor(log(max_c))) + 1 + g_sharedexp_bias; + const int max_s = floor((max_c / (pow(2.0f, exp_p - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f); + const int exp_s = (max_s < pow(2.0f, g_sharedexp_mantissabits)) ? exp_p : exp_p + 1; + + RGB9E5Data output; + output.R = floor((red_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f); + output.G = floor((green_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f); + output.B = floor((blue_c / (pow(2.0f, exp_s - g_sharedexp_bias - g_sharedexp_mantissabits))) + 0.5f); + output.E = exp_s; + + return *reinterpret_cast(&output); +} + +void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue) +{ + const RGB9E5Data *inputData = reinterpret_cast(&input); + + *red = inputData->R * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits); + *green = inputData->G * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits); + *blue = inputData->B * pow(2.0f, (int)inputData->E - g_sharedexp_bias - g_sharedexp_mantissabits); +} + +} diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h new file mode 100644 index 0000000000..f32663fa02 --- /dev/null +++ b/src/3rdparty/angle/src/common/mathutil.h @@ -0,0 +1,545 @@ +// +// 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. +// + +// mathutil.h: Math and bit manipulation functions. + +#ifndef LIBGLESV2_MATHUTIL_H_ +#define LIBGLESV2_MATHUTIL_H_ + +#include "common/debug.h" +#include "common/platform.h" + +#include +#include +#include + +namespace gl +{ + +const unsigned int Float32One = 0x3F800000; +const unsigned short Float16One = 0x3C00; + +struct Vector4 +{ + Vector4() {} + Vector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {} + + float x; + float y; + float z; + float w; +}; + +inline bool isPow2(int x) +{ + return (x & (x - 1)) == 0 && (x != 0); +} + +inline int log2(int x) +{ + int r = 0; + while ((x >> r) > 1) r++; + return r; +} + +inline unsigned int ceilPow2(unsigned int x) +{ + if (x != 0) x--; + x |= x >> 1; + x |= x >> 2; + x |= x >> 4; + x |= x >> 8; + x |= x >> 16; + x++; + + return x; +} + +inline int clampToInt(unsigned int x) +{ + return static_cast(std::min(x, static_cast(std::numeric_limits::max()))); +} + +template +inline DestT clampCast(SrcT value) +{ + // This assumes SrcT can properly represent DestT::min/max + // Unfortunately we can't use META_ASSERT without C++11 constexpr support + ASSERT(static_cast(static_cast(std::numeric_limits::min())) == std::numeric_limits::min()); + ASSERT(static_cast(static_cast(std::numeric_limits::max())) == std::numeric_limits::max()); + + SrcT lo = static_cast(std::numeric_limits::min()); + SrcT hi = static_cast(std::numeric_limits::max()); + return static_cast(value > lo ? (value > hi ? hi : value) : lo); +} + +template +inline T clamp(T x, MIN min, MAX max) +{ + // Since NaNs fail all comparison tests, a NaN value will default to min + return x > min ? (x > max ? max : x) : min; +} + +inline float clamp01(float x) +{ + return clamp(x, 0.0f, 1.0f); +} + +template +inline unsigned int unorm(float x) +{ + const unsigned int max = 0xFFFFFFFF >> (32 - n); + + if (x > 1) + { + return max; + } + else if (x < 0) + { + return 0; + } + else + { + return (unsigned int)(max * x + 0.5f); + } +} + +inline bool supportsSSE2() +{ +#ifdef ANGLE_PLATFORM_WINDOWS + static bool checked = false; + static bool supports = false; + + if (checked) + { + return supports; + } + +#if defined(_M_IX86) || defined(_M_AMD64) // ARM doesn't provide __cpuid() + int info[4]; + __cpuid(info, 0); + + if (info[0] >= 1) + { + __cpuid(info, 1); + + supports = (info[3] >> 26) & 1; + } +#endif + + checked = true; + + return supports; +#else + UNIMPLEMENTED(); + return false; +#endif +} + +template +destType bitCast(const sourceType &source) +{ + size_t copySize = std::min(sizeof(destType), sizeof(sourceType)); + destType output; + memcpy(&output, &source, copySize); + return output; +} + +inline unsigned short float32ToFloat16(float fp32) +{ + unsigned int fp32i = (unsigned int&)fp32; + unsigned int sign = (fp32i & 0x80000000) >> 16; + unsigned int abs = fp32i & 0x7FFFFFFF; + + if(abs > 0x47FFEFFF) // Infinity + { + return sign | 0x7FFF; + } + else if(abs < 0x38800000) // Denormal + { + unsigned int mantissa = (abs & 0x007FFFFF) | 0x00800000; + int e = 113 - (abs >> 23); + + if(e < 24) + { + abs = mantissa >> e; + } + else + { + abs = 0; + } + + return sign | (abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13; + } + else + { + return sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13; + } +} + +float float16ToFloat32(unsigned short h); + +unsigned int convertRGBFloatsTo999E5(float red, float green, float blue); +void convert999E5toRGBFloats(unsigned int input, float *red, float *green, float *blue); + +inline unsigned short float32ToFloat11(float fp32) +{ + const unsigned int float32MantissaMask = 0x7FFFFF; + const unsigned int float32ExponentMask = 0x7F800000; + const unsigned int float32SignMask = 0x80000000; + const unsigned int float32ValueMask = ~float32SignMask; + const unsigned int float32ExponentFirstBit = 23; + const unsigned int float32ExponentBias = 127; + + const unsigned short float11Max = 0x7BF; + const unsigned short float11MantissaMask = 0x3F; + const unsigned short float11ExponentMask = 0x7C0; + const unsigned short float11BitMask = 0x7FF; + const unsigned int float11ExponentBias = 14; + + const unsigned int float32Maxfloat11 = 0x477E0000; + const unsigned int float32Minfloat11 = 0x38800000; + + const unsigned int float32Bits = bitCast(fp32); + const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask; + + unsigned int float32Val = float32Bits & float32ValueMask; + + if ((float32Val & float32ExponentMask) == float32ExponentMask) + { + // INF or NAN + if ((float32Val & float32MantissaMask) != 0) + { + return float11ExponentMask | (((float32Val >> 17) | (float32Val >> 11) | (float32Val >> 6) | (float32Val)) & float11MantissaMask); + } + else if (float32Sign) + { + // -INF is clamped to 0 since float11 is positive only + return 0; + } + else + { + return float11ExponentMask; + } + } + else if (float32Sign) + { + // float11 is positive only, so clamp to zero + return 0; + } + else if (float32Val > float32Maxfloat11) + { + // The number is too large to be represented as a float11, set to max + return float11Max; + } + else + { + if (float32Val < float32Minfloat11) + { + // The number is too small to be represented as a normalized float11 + // Convert it to a denormalized value. + const unsigned int shift = (float32ExponentBias - float11ExponentBias) - (float32Val >> float32ExponentFirstBit); + float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift; + } + else + { + // Rebias the exponent to represent the value as a normalized float11 + float32Val += 0xC8000000; + } + + return ((float32Val + 0xFFFF + ((float32Val >> 17) & 1)) >> 17) & float11BitMask; + } +} + +inline unsigned short float32ToFloat10(float fp32) +{ + const unsigned int float32MantissaMask = 0x7FFFFF; + const unsigned int float32ExponentMask = 0x7F800000; + const unsigned int float32SignMask = 0x80000000; + const unsigned int float32ValueMask = ~float32SignMask; + const unsigned int float32ExponentFirstBit = 23; + const unsigned int float32ExponentBias = 127; + + const unsigned short float10Max = 0x3DF; + const unsigned short float10MantissaMask = 0x1F; + const unsigned short float10ExponentMask = 0x3E0; + const unsigned short float10BitMask = 0x3FF; + const unsigned int float10ExponentBias = 14; + + const unsigned int float32Maxfloat10 = 0x477C0000; + const unsigned int float32Minfloat10 = 0x38800000; + + const unsigned int float32Bits = bitCast(fp32); + const bool float32Sign = (float32Bits & float32SignMask) == float32SignMask; + + unsigned int float32Val = float32Bits & float32ValueMask; + + if ((float32Val & float32ExponentMask) == float32ExponentMask) + { + // INF or NAN + if ((float32Val & float32MantissaMask) != 0) + { + return float10ExponentMask | (((float32Val >> 18) | (float32Val >> 13) | (float32Val >> 3) | (float32Val)) & float10MantissaMask); + } + else if (float32Sign) + { + // -INF is clamped to 0 since float11 is positive only + return 0; + } + else + { + return float10ExponentMask; + } + } + else if (float32Sign) + { + // float10 is positive only, so clamp to zero + return 0; + } + else if (float32Val > float32Maxfloat10) + { + // The number is too large to be represented as a float11, set to max + return float10Max; + } + else + { + if (float32Val < float32Minfloat10) + { + // The number is too small to be represented as a normalized float11 + // Convert it to a denormalized value. + const unsigned int shift = (float32ExponentBias - float10ExponentBias) - (float32Val >> float32ExponentFirstBit); + float32Val = ((1 << float32ExponentFirstBit) | (float32Val & float32MantissaMask)) >> shift; + } + else + { + // Rebias the exponent to represent the value as a normalized float11 + float32Val += 0xC8000000; + } + + return ((float32Val + 0x1FFFF + ((float32Val >> 18) & 1)) >> 18) & float10BitMask; + } +} + +inline float float11ToFloat32(unsigned short fp11) +{ + unsigned short exponent = (fp11 >> 6) & 0x1F; + unsigned short mantissa = fp11 & 0x3F; + + if (exponent == 0x1F) + { + // INF or NAN + return bitCast(0x7f800000 | (mantissa << 17)); + } + else + { + if (exponent != 0) + { + // normalized + } + else if (mantissa != 0) + { + // The value is denormalized + exponent = 1; + + do + { + exponent--; + mantissa <<= 1; + } + while ((mantissa & 0x40) == 0); + + mantissa = mantissa & 0x3F; + } + else // The value is zero + { + exponent = -112; + } + + return bitCast(((exponent + 112) << 23) | (mantissa << 17)); + } +} + +inline float float10ToFloat32(unsigned short fp11) +{ + unsigned short exponent = (fp11 >> 5) & 0x1F; + unsigned short mantissa = fp11 & 0x1F; + + if (exponent == 0x1F) + { + // INF or NAN + return bitCast(0x7f800000 | (mantissa << 17)); + } + else + { + if (exponent != 0) + { + // normalized + } + else if (mantissa != 0) + { + // The value is denormalized + exponent = 1; + + do + { + exponent--; + mantissa <<= 1; + } + while ((mantissa & 0x20) == 0); + + mantissa = mantissa & 0x1F; + } + else // The value is zero + { + exponent = -112; + } + + return bitCast(((exponent + 112) << 23) | (mantissa << 18)); + } +} + +template +inline float normalizedToFloat(T input) +{ + META_ASSERT(std::numeric_limits::is_integer); + + const float inverseMax = 1.0f / std::numeric_limits::max(); + return input * inverseMax; +} + +template +inline float normalizedToFloat(T input) +{ + META_ASSERT(std::numeric_limits::is_integer); + META_ASSERT(inputBitCount < (sizeof(T) * 8)); + + const float inverseMax = 1.0f / ((1 << inputBitCount) - 1); + return input * inverseMax; +} + +template +inline T floatToNormalized(float input) +{ + return std::numeric_limits::max() * input + 0.5f; +} + +template +inline T floatToNormalized(float input) +{ + META_ASSERT(outputBitCount < (sizeof(T) * 8)); + return ((1 << outputBitCount) - 1) * input + 0.5f; +} + +template +inline T getShiftedData(T input) +{ + META_ASSERT(inputBitCount + inputBitStart <= (sizeof(T) * 8)); + const T mask = (1 << inputBitCount) - 1; + return (input >> inputBitStart) & mask; +} + +template +inline T shiftData(T input) +{ + META_ASSERT(inputBitCount + inputBitStart <= (sizeof(T) * 8)); + const T mask = (1 << inputBitCount) - 1; + return (input & mask) << inputBitStart; +} + + +inline unsigned char average(unsigned char a, unsigned char b) +{ + return ((a ^ b) >> 1) + (a & b); +} + +inline signed char average(signed char a, signed char b) +{ + return ((short)a + (short)b) / 2; +} + +inline unsigned short average(unsigned short a, unsigned short b) +{ + return ((a ^ b) >> 1) + (a & b); +} + +inline signed short average(signed short a, signed short b) +{ + return ((int)a + (int)b) / 2; +} + +inline unsigned int average(unsigned int a, unsigned int b) +{ + return ((a ^ b) >> 1) + (a & b); +} + +inline signed int average(signed int a, signed int b) +{ + return ((long long)a + (long long)b) / 2; +} + +inline float average(float a, float b) +{ + return (a + b) * 0.5f; +} + +inline unsigned short averageHalfFloat(unsigned short a, unsigned short b) +{ + return float32ToFloat16((float16ToFloat32(a) + float16ToFloat32(b)) * 0.5f); +} + +inline unsigned int averageFloat11(unsigned int a, unsigned int b) +{ + return float32ToFloat11((float11ToFloat32(a) + float11ToFloat32(b)) * 0.5f); +} + +inline unsigned int averageFloat10(unsigned int a, unsigned int b) +{ + return float32ToFloat10((float10ToFloat32(a) + float10ToFloat32(b)) * 0.5f); +} + +} + +namespace rx +{ + +struct Range +{ + Range() {} + Range(int lo, int hi) : start(lo), end(hi) { ASSERT(lo <= hi); } + + int start; + int end; +}; + +template +T roundUp(const T value, const T alignment) +{ + return value + alignment - 1 - (value - 1) % alignment; +} + +template +inline bool IsUnsignedAdditionSafe(T lhs, T rhs) +{ + META_ASSERT(!std::numeric_limits::is_signed); + return (rhs <= std::numeric_limits::max() - lhs); +} + +template +inline bool IsUnsignedMultiplicationSafe(T lhs, T rhs) +{ + META_ASSERT(!std::numeric_limits::is_signed); + return (lhs == T(0) || rhs == T(0) || (rhs <= std::numeric_limits::max() / lhs)); +} + +template +inline bool IsIntegerCastSafe(BigIntT bigValue) +{ + return (static_cast(static_cast(bigValue)) == bigValue); +} + +} + +#endif // LIBGLESV2_MATHUTIL_H_ diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h new file mode 100644 index 0000000000..e16e7ac0c2 --- /dev/null +++ b/src/3rdparty/angle/src/common/platform.h @@ -0,0 +1,73 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// platform.h: Operating system specific includes and defines. + +#ifndef COMMON_PLATFORM_H_ +#define COMMON_PLATFORM_H_ + +#if defined(_WIN32) || defined(_WIN64) +# define ANGLE_PLATFORM_WINDOWS 1 +# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_PC_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) +# define ANGLE_PLATFORM_WINRT 1 +# endif +#elif defined(__APPLE__) +# define ANGLE_PLATFORM_APPLE 1 +# define ANGLE_PLATFORM_POSIX 1 +#elif defined(__linux__) +# define ANGLE_PLATFORM_LINUX 1 +# define ANGLE_PLATFORM_POSIX 1 +#elif defined(ANDROID) +# define ANGLE_PLATFORM_ANDROID 1 +# define ANGLE_PLATFORM_POSIX 1 +#elif defined(__FreeBSD__) || \ + defined(__OpenBSD__) || \ + defined(__NetBSD__) || \ + defined(__DragonFly__) || \ + defined(__sun) || \ + defined(__GLIBC__) || \ + defined(__GNU__) || \ + defined(__QNX__) +# define ANGLE_PLATFORM_POSIX 1 +#else +# error Unsupported platform. +#endif + +#ifdef ANGLE_PLATFORM_WINDOWS +# ifndef STRICT +# define STRICT 1 +# endif +# ifndef WIN32_LEAN_AND_MEAN +# define WIN32_LEAN_AND_MEAN 1 +# endif +# ifndef NOMINMAX +# define NOMINMAX 1 +# endif + +# include +# include + +# if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_PERF) +# include +# endif + +# if defined(ANGLE_ENABLE_D3D11) +# include +# include +# include +# include +# include +# 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 new file mode 100644 index 0000000000..0442d81500 --- /dev/null +++ b/src/3rdparty/angle/src/common/shadervars.h @@ -0,0 +1,157 @@ +// +// 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/common/tls.cpp b/src/3rdparty/angle/src/common/tls.cpp new file mode 100644 index 0000000000..c46fab5303 --- /dev/null +++ b/src/3rdparty/angle/src/common/tls.cpp @@ -0,0 +1,103 @@ +// +// 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. +// + +// tls.cpp: Simple cross-platform interface for thread local storage. + +#include "common/tls.h" + +#include + +#if defined(ANGLE_PLATFORM_WINRT) +#include +std::vector *tls = nullptr; +std::vector *freeIndices = nullptr; +#endif + +TLSIndex CreateTLSIndex() +{ + TLSIndex index; + +#if defined(ANGLE_PLATFORM_WINRT) + if (!tls) + tls = new std::vector; + if (freeIndices && !freeIndices->empty()) { + index = freeIndices->back(); + freeIndices->pop_back(); + return index; + } else { + tls->push_back(nullptr); + return tls->size() - 1; + } +#elif defined(ANGLE_PLATFORM_WINDOWS) + index = TlsAlloc(); +#elif defined(ANGLE_PLATFORM_POSIX) + // Create global pool key + if ((pthread_key_create(&index, NULL)) != 0) + { + index = TLS_INVALID_INDEX; + } +#endif + + assert(index != TLS_INVALID_INDEX && "CreateTLSIndex(): Unable to allocate Thread Local Storage"); + return index; +} + +bool DestroyTLSIndex(TLSIndex index) +{ + assert(index != TLS_INVALID_INDEX && "DestroyTLSIndex(): Invalid TLS Index"); + if (index == TLS_INVALID_INDEX) + { + return false; + } + +#if defined(ANGLE_PLATFORM_WINRT) + if (!freeIndices) + freeIndices = new std::vector; + freeIndices->push_back(index); + return true; +#elif ANGLE_PLATFORM_WINDOWS + return (TlsFree(index) == TRUE); +#elif defined(ANGLE_PLATFORM_POSIX) + return (pthread_key_delete(index) == 0); +#endif +} + +bool SetTLSValue(TLSIndex index, void *value) +{ + assert(index != TLS_INVALID_INDEX && "SetTLSValue(): Invalid TLS Index"); + if (index == TLS_INVALID_INDEX) + { + return false; + } + +#if defined(ANGLE_PLATFORM_WINRT) + tls->at(index) = value; + return true; +#elif defined(ANGLE_PLATFORM_WINDOWS) + return (TlsSetValue(index, value) == TRUE); +#elif defined(ANGLE_PLATFORM_POSIX) + return (pthread_setspecific(index, value) == 0); +#endif +} + +void *GetTLSValue(TLSIndex index) +{ +#if !defined(ANGLE_PLATFORM_WINRT) // Valid on WinRT, as Alloc handles the index creation + assert(index != TLS_INVALID_INDEX && "GetTLSValue(): Invalid TLS Index"); +#endif + if (index == TLS_INVALID_INDEX) + { + return NULL; + } + +#if defined(ANGLE_PLATFORM_WINRT) + return tls->at(index); +#elif defined(ANGLE_PLATFORM_WINDOWS) + return TlsGetValue(index); +#elif defined(ANGLE_PLATFORM_POSIX) + return pthread_getspecific(index); +#endif +} diff --git a/src/3rdparty/angle/src/common/tls.h b/src/3rdparty/angle/src/common/tls.h new file mode 100644 index 0000000000..c40ae1a061 --- /dev/null +++ b/src/3rdparty/angle/src/common/tls.h @@ -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. +// + +// tls.h: Simple cross-platform interface for thread local storage. + +#ifndef COMMON_TLS_H_ +#define COMMON_TLS_H_ + +#include "common/platform.h" + +#if defined(ANGLE_PLATFORM_WINRT) + typedef size_t TLSIndex; +# define TLS_OUT_OF_INDEXES (static_cast(-1)) +# define TLS_INVALID_INDEX TLS_OUT_OF_INDEXES +#elif defined(ANGLE_PLATFORM_WINDOWS) + typedef DWORD TLSIndex; +# define TLS_INVALID_INDEX (TLS_OUT_OF_INDEXES) +#elif defined(ANGLE_PLATFORM_POSIX) +# include +# include +# include + typedef pthread_key_t TLSIndex; +# define TLS_INVALID_INDEX (static_cast(-1)) +#else +# error Unsupported platform. +#endif + +TLSIndex CreateTLSIndex(); +bool DestroyTLSIndex(TLSIndex index); + +bool SetTLSValue(TLSIndex index, void *value); +void *GetTLSValue(TLSIndex index); + +#endif // COMMON_TLS_H_ diff --git a/src/3rdparty/angle/src/common/utilities.cpp b/src/3rdparty/angle/src/common/utilities.cpp new file mode 100644 index 0000000000..4b8e325d22 --- /dev/null +++ b/src/3rdparty/angle/src/common/utilities.cpp @@ -0,0 +1,527 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// utilities.cpp: Conversion functions and other utility routines. + +#include "common/utilities.h" +#include "common/mathutil.h" +#include "common/platform.h" +#if defined(ANGLE_PLATFORM_WINRT) +# include +# include +# include +# include + using namespace Microsoft::WRL; + using namespace ABI::Windows::Storage; +#endif + +#include + +namespace gl +{ + +int VariableComponentCount(GLenum type) +{ + return VariableRowCount(type) * VariableColumnCount(type); +} + +GLenum VariableComponentType(GLenum type) +{ + switch(type) + { + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + return GL_BOOL; + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x3: + return GL_FLOAT; + case GL_INT: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + return GL_INT; + case GL_UNSIGNED_INT: + case GL_UNSIGNED_INT_VEC2: + case GL_UNSIGNED_INT_VEC3: + case GL_UNSIGNED_INT_VEC4: + return GL_UNSIGNED_INT; + default: + UNREACHABLE(); + } + + return GL_NONE; +} + +size_t VariableComponentSize(GLenum type) +{ + switch(type) + { + case GL_BOOL: return sizeof(GLint); + case GL_FLOAT: return sizeof(GLfloat); + case GL_INT: return sizeof(GLint); + case GL_UNSIGNED_INT: return sizeof(GLuint); + default: UNREACHABLE(); + } + + return 0; +} + +size_t VariableInternalSize(GLenum type) +{ + // Expanded to 4-element vectors + return VariableComponentSize(VariableComponentType(type)) * VariableRowCount(type) * 4; +} + +size_t VariableExternalSize(GLenum type) +{ + return VariableComponentSize(VariableComponentType(type)) * VariableComponentCount(type); +} + +GLenum VariableBoolVectorType(GLenum type) +{ + switch (type) + { + case GL_FLOAT: + case GL_INT: + case GL_UNSIGNED_INT: + return GL_BOOL; + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_UNSIGNED_INT_VEC2: + return GL_BOOL_VEC2; + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_UNSIGNED_INT_VEC3: + return GL_BOOL_VEC3; + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_UNSIGNED_INT_VEC4: + return GL_BOOL_VEC4; + + default: + UNREACHABLE(); + return GL_NONE; + } +} + +int VariableRowCount(GLenum type) +{ + switch (type) + { + case GL_NONE: + case GL_STRUCT_ANGLEX: + return 0; + case GL_BOOL: + case GL_FLOAT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_BOOL_VEC2: + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_UNSIGNED_INT_VEC2: + case GL_BOOL_VEC3: + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_UNSIGNED_INT_VEC3: + case GL_BOOL_VEC4: + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_UNSIGNED_INT_VEC4: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_EXTERNAL_OES: + case GL_SAMPLER_2D_RECT_ARB: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + return 1; + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT4x2: + return 2; + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT4x3: + return 3; + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x4: + return 4; + default: + UNREACHABLE(); + } + + return 0; +} + +int VariableColumnCount(GLenum type) +{ + switch (type) + { + case GL_NONE: + case GL_STRUCT_ANGLEX: + return 0; + case GL_BOOL: + case GL_FLOAT: + case GL_INT: + case GL_UNSIGNED_INT: + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_SAMPLER_EXTERNAL_OES: + case GL_SAMPLER_2D_RECT_ARB: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + return 1; + case GL_BOOL_VEC2: + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_UNSIGNED_INT_VEC2: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT2x4: + return 2; + case GL_BOOL_VEC3: + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_UNSIGNED_INT_VEC3: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_MAT3x4: + return 3; + case GL_BOOL_VEC4: + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_UNSIGNED_INT_VEC4: + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: + return 4; + default: + UNREACHABLE(); + } + + return 0; +} + +bool IsSampler(GLenum type) +{ + switch (type) + { + case GL_SAMPLER_2D: + case GL_SAMPLER_3D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_2D_ARRAY: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + return true; + } + + return false; +} + +bool IsMatrixType(GLenum type) +{ + return VariableRowCount(type) > 1; +} + +GLenum TransposeMatrixType(GLenum type) +{ + if (!IsMatrixType(type)) + { + return type; + } + + switch (type) + { + case GL_FLOAT_MAT2: return GL_FLOAT_MAT2; + case GL_FLOAT_MAT3: return GL_FLOAT_MAT3; + case GL_FLOAT_MAT4: return GL_FLOAT_MAT4; + case GL_FLOAT_MAT2x3: return GL_FLOAT_MAT3x2; + case GL_FLOAT_MAT3x2: return GL_FLOAT_MAT2x3; + case GL_FLOAT_MAT2x4: return GL_FLOAT_MAT4x2; + case GL_FLOAT_MAT4x2: return GL_FLOAT_MAT2x4; + case GL_FLOAT_MAT3x4: return GL_FLOAT_MAT4x3; + case GL_FLOAT_MAT4x3: return GL_FLOAT_MAT3x4; + default: UNREACHABLE(); return GL_NONE; + } +} + +int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix) +{ + ASSERT(IsMatrixType(type)); + return isRowMajorMatrix ? VariableRowCount(type) : VariableColumnCount(type); +} + +int MatrixComponentCount(GLenum type, bool isRowMajorMatrix) +{ + ASSERT(IsMatrixType(type)); + return isRowMajorMatrix ? VariableColumnCount(type) : VariableRowCount(type); +} + +int VariableRegisterCount(GLenum type) +{ + return IsMatrixType(type) ? VariableColumnCount(type) : 1; +} + +int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize) +{ + ASSERT(allocationSize <= bitsSize); + + unsigned int mask = std::numeric_limits::max() >> (std::numeric_limits::digits - allocationSize); + + for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++) + { + if ((*bits & mask) == 0) + { + *bits |= mask; + return i; + } + + mask <<= 1; + } + + return -1; +} + +bool IsCubemapTextureTarget(GLenum target) +{ + return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); +} + +bool IsTriangleMode(GLenum drawMode) +{ + switch (drawMode) + { + case GL_TRIANGLES: + case GL_TRIANGLE_FAN: + case GL_TRIANGLE_STRIP: + return true; + case GL_POINTS: + case GL_LINES: + case GL_LINE_LOOP: + case GL_LINE_STRIP: + return false; + default: UNREACHABLE(); + } + + return false; +} + +// [OpenGL ES SL 3.00.4] Section 11 p. 120 +// Vertex Outs/Fragment Ins packing priorities +int VariableSortOrder(GLenum type) +{ + switch (type) + { + // 1. Arrays of mat4 and mat4 + // Non-square matrices of type matCxR consume the same space as a square + // matrix of type matN where N is the greater of C and R + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: + return 0; + + // 2. Arrays of mat2 and mat2 (since they occupy full rows) + case GL_FLOAT_MAT2: + return 1; + + // 3. Arrays of vec4 and vec4 + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_BOOL_VEC4: + case GL_UNSIGNED_INT_VEC4: + return 2; + + // 4. Arrays of mat3 and mat3 + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT3x2: + return 3; + + // 5. Arrays of vec3 and vec3 + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_BOOL_VEC3: + case GL_UNSIGNED_INT_VEC3: + return 4; + + // 6. Arrays of vec2 and vec2 + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_BOOL_VEC2: + case GL_UNSIGNED_INT_VEC2: + return 5; + + // 7. Single component types + case GL_FLOAT: + case GL_INT: + case GL_BOOL: + case GL_UNSIGNED_INT: + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_EXTERNAL_OES: + case GL_SAMPLER_2D_RECT_ARB: + case GL_SAMPLER_2D_ARRAY: + case GL_SAMPLER_3D: + case GL_INT_SAMPLER_2D: + case GL_INT_SAMPLER_3D: + case GL_INT_SAMPLER_CUBE: + case GL_INT_SAMPLER_2D_ARRAY: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: + case GL_SAMPLER_2D_SHADOW: + case GL_SAMPLER_2D_ARRAY_SHADOW: + case GL_SAMPLER_CUBE_SHADOW: + return 6; + + default: + UNREACHABLE(); + return 0; + } +} + +} + +std::string getTempPath() +{ +#if defined(ANGLE_PLATFORM_WINRT) + static std::string path; + + while (path.empty()) + { + ComPtr factory; + Wrappers::HStringReference classId(RuntimeClass_Windows_Storage_ApplicationData); + HRESULT result = RoGetActivationFactory(classId.Get(), IID_PPV_ARGS(&factory)); + if (FAILED(result)) + break; + + ComPtr applicationData; + result = factory->get_Current(&applicationData); + if (FAILED(result)) + break; + + ComPtr storageFolder; + result = applicationData->get_LocalFolder(&storageFolder); + if (FAILED(result)) + break; + + ComPtr localFolder; + result = storageFolder.As(&localFolder); + if (FAILED(result)) + break; + + HSTRING localFolderPath; + result = localFolder->get_Path(&localFolderPath); + if (FAILED(result)) + break; + + std::wstring_convert< std::codecvt_utf8 > converter; + path = converter.to_bytes(WindowsGetStringRawBuffer(localFolderPath, NULL)); + if (path.empty()) + { + UNREACHABLE(); + break; + } + } + + return path; +#elif defined(ANGLE_PLATFORM_WINDOWS) + char path[MAX_PATH]; + DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path); + if (pathLen == 0) + { + UNREACHABLE(); + return std::string(); + } + + UINT unique = GetTempFileNameA(path, "sh", 0, path); + if (unique == 0) + { + UNREACHABLE(); + return std::string(); + } + + return path; +#else + UNIMPLEMENTED(); + return ""; +#endif +} + +void writeFile(const char* path, const void* content, size_t size) +{ + FILE* file = fopen(path, "w"); + if (!file) + { + UNREACHABLE(); + return; + } + + fwrite(content, sizeof(char), size, file); + fclose(file); +} diff --git a/src/3rdparty/angle/src/common/utilities.h b/src/3rdparty/angle/src/common/utilities.h new file mode 100644 index 0000000000..a823184ecd --- /dev/null +++ b/src/3rdparty/angle/src/common/utilities.h @@ -0,0 +1,52 @@ +// +// 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. +// + +// utilities.h: Conversion functions and other utility routines. + +#ifndef LIBGLESV2_UTILITIES_H +#define LIBGLESV2_UTILITIES_H + +#include "angle_gl.h" +#include +#include + +namespace gl +{ + +int VariableComponentCount(GLenum type); +GLenum VariableComponentType(GLenum type); +size_t VariableComponentSize(GLenum type); +size_t VariableInternalSize(GLenum type); +size_t VariableExternalSize(GLenum type); +GLenum VariableBoolVectorType(GLenum type); +int VariableRowCount(GLenum type); +int VariableColumnCount(GLenum type); +bool IsSampler(GLenum type); +bool IsMatrixType(GLenum type); +GLenum TransposeMatrixType(GLenum type); +int VariableRegisterCount(GLenum type); +int MatrixRegisterCount(GLenum type, bool isRowMajorMatrix); +int MatrixComponentCount(GLenum type, bool isRowMajorMatrix); +int VariableSortOrder(GLenum type); + +int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize); + +bool IsCubemapTextureTarget(GLenum target); + +bool IsTriangleMode(GLenum drawMode); + +// [OpenGL ES 3.0.2] Section 2.3.1 page 14 +// Data Conversion For State-Setting Commands +// Floating-point values are rounded to the nearest integer, instead of truncated, as done by static_cast. +template outT iround(GLfloat value) { return static_cast(value > 0.0f ? floor(value + 0.5f) : ceil(value - 0.5f)); } +template outT uiround(GLfloat value) { return static_cast(value + 0.5f); } + +} + +std::string getTempPath(); +void writeFile(const char* path, const void* data, size_t size); + +#endif // LIBGLESV2_UTILITIES_H diff --git a/src/3rdparty/angle/src/common/version.h b/src/3rdparty/angle/src/common/version.h index f6ae19f541..f01e0242cb 100644 --- a/src/3rdparty/angle/src/common/version.h +++ b/src/3rdparty/angle/src/common/version.h @@ -1,7 +1,7 @@ -#include "commit.h" +#include "../commit.h" -#define ANGLE_MAJOR_VERSION 1 -#define ANGLE_MINOR_VERSION 3 +#define ANGLE_MAJOR_VERSION 2 +#define ANGLE_MINOR_VERSION 1 #define ANGLE_STRINGIFY(x) #x #define ANGLE_MACRO_STRINGIFY(x) ANGLE_STRINGIFY(x) diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp index a7ce862bcb..cf60bc2349 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.cpp @@ -16,8 +16,8 @@ Diagnostics::~Diagnostics() } void Diagnostics::report(ID id, - const SourceLocation& loc, - const std::string& text) + const SourceLocation &loc, + const std::string &text) { // TODO(alokp): Keep a count of errors and warnings. print(id, loc, text); @@ -41,86 +41,86 @@ std::string Diagnostics::message(ID id) { // Errors begin. case PP_INTERNAL_ERROR: - return "internal error"; + return "internal error"; case PP_OUT_OF_MEMORY: - return "out of memory"; + return "out of memory"; case PP_INVALID_CHARACTER: - return "invalid character"; + return "invalid character"; case PP_INVALID_NUMBER: - return "invalid number"; + return "invalid number"; case PP_INTEGER_OVERFLOW: - return "integer overflow"; + return "integer overflow"; case PP_FLOAT_OVERFLOW: - return "float overflow"; + return "float overflow"; case PP_TOKEN_TOO_LONG: - return "token too long"; + return "token too long"; case PP_INVALID_EXPRESSION: - return "invalid expression"; + return "invalid expression"; case PP_DIVISION_BY_ZERO: - return "division by zero"; + return "division by zero"; case PP_EOF_IN_COMMENT: - return "unexpected end of file found in comment"; + return "unexpected end of file found in comment"; case PP_UNEXPECTED_TOKEN: - return "unexpected token"; + return "unexpected token"; case PP_DIRECTIVE_INVALID_NAME: - return "invalid directive name"; + return "invalid directive name"; case PP_MACRO_NAME_RESERVED: - return "macro name is reserved"; + return "macro name is reserved"; case PP_MACRO_REDEFINED: - return "macro redefined"; + return "macro redefined"; case PP_MACRO_PREDEFINED_REDEFINED: - return "predefined macro redefined"; + return "predefined macro redefined"; case PP_MACRO_PREDEFINED_UNDEFINED: - return "predefined macro undefined"; + return "predefined macro undefined"; case PP_MACRO_UNTERMINATED_INVOCATION: - return "unterminated macro invocation"; + return "unterminated macro invocation"; case PP_MACRO_TOO_FEW_ARGS: - return "Not enough arguments for macro"; + return "Not enough arguments for macro"; case PP_MACRO_TOO_MANY_ARGS: - return "Too many arguments for macro"; + return "Too many arguments for macro"; case PP_CONDITIONAL_ENDIF_WITHOUT_IF: - return "unexpected #endif found without a matching #if"; + return "unexpected #endif found without a matching #if"; case PP_CONDITIONAL_ELSE_WITHOUT_IF: - return "unexpected #else found without a matching #if"; + return "unexpected #else found without a matching #if"; case PP_CONDITIONAL_ELSE_AFTER_ELSE: - return "unexpected #else found after another #else"; + return "unexpected #else found after another #else"; case PP_CONDITIONAL_ELIF_WITHOUT_IF: - return "unexpected #elif found without a matching #if"; + return "unexpected #elif found without a matching #if"; case PP_CONDITIONAL_ELIF_AFTER_ELSE: - return "unexpected #elif found after #else"; + return "unexpected #elif found after #else"; case PP_CONDITIONAL_UNTERMINATED: - return "unexpected end of file found in conditional block"; + return "unexpected end of file found in conditional block"; case PP_INVALID_EXTENSION_NAME: - return "invalid extension name"; + return "invalid extension name"; case PP_INVALID_EXTENSION_BEHAVIOR: - return "invalid extension behavior"; + return "invalid extension behavior"; case PP_INVALID_EXTENSION_DIRECTIVE: - return "invalid extension directive"; + return "invalid extension directive"; case PP_INVALID_VERSION_NUMBER: - return "invalid version number"; + return "invalid version number"; case PP_INVALID_VERSION_DIRECTIVE: - return "invalid version directive"; + return "invalid version directive"; case PP_VERSION_NOT_FIRST_STATEMENT: return "#version directive must occur before anything else, " "except for comments and white space"; case PP_INVALID_LINE_NUMBER: - return "invalid line number"; + return "invalid line number"; case PP_INVALID_FILE_NUMBER: - return "invalid file number"; + return "invalid file number"; case PP_INVALID_LINE_DIRECTIVE: - return "invalid line directive"; + return "invalid line directive"; // Errors end. // Warnings begin. case PP_EOF_IN_DIRECTIVE: - return "unexpected end of file found in directive"; + return "unexpected end of file found in directive"; case PP_CONDITIONAL_UNEXPECTED_TOKEN: - return "unexpected token after conditional expression"; + return "unexpected token after conditional expression"; case PP_UNRECOGNIZED_PRAGMA: - return "unrecognized pragma"; + return "unrecognized pragma"; // Warnings end. default: - assert(false); - return ""; + assert(false); + return ""; } } diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h index 2c8c539137..a7587ed657 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h @@ -72,15 +72,15 @@ class Diagnostics virtual ~Diagnostics(); - void report(ID id, const SourceLocation& loc, const std::string& text); + void report(ID id, const SourceLocation &loc, const std::string &text); protected: Severity severity(ID id); std::string message(ID id); virtual void print(ID id, - const SourceLocation& loc, - const std::string& text) = 0; + const SourceLocation &loc, + const std::string &text) = 0; }; } // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h index 2aaeec2818..040b25c6a2 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h @@ -23,19 +23,19 @@ class DirectiveHandler public: virtual ~DirectiveHandler(); - virtual void handleError(const SourceLocation& loc, - const std::string& msg) = 0; + virtual void handleError(const SourceLocation &loc, + const std::string &msg) = 0; // Handle pragma of form: #pragma name[(value)] - virtual void handlePragma(const SourceLocation& loc, - const std::string& name, - const std::string& value) = 0; + virtual void handlePragma(const SourceLocation &loc, + const std::string &name, + const std::string &value) = 0; - virtual void handleExtension(const SourceLocation& loc, - const std::string& name, - const std::string& behavior) = 0; + virtual void handleExtension(const SourceLocation &loc, + const std::string &name, + const std::string &behavior) = 0; - virtual void handleVersion(const SourceLocation& loc, + virtual void handleVersion(const SourceLocation &loc, int version) = 0; }; diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp index ebec79804d..6434d5cb5c 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2011-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -35,9 +35,8 @@ enum DirectiveType DIRECTIVE_VERSION, DIRECTIVE_LINE }; -} // namespace -static DirectiveType getDirective(const pp::Token* token) +DirectiveType getDirective(const pp::Token *token) { static const std::string kDirectiveDefine("define"); static const std::string kDirectiveUndef("undef"); @@ -58,35 +57,35 @@ static DirectiveType getDirective(const pp::Token* token) if (token->text == kDirectiveDefine) return DIRECTIVE_DEFINE; - else if (token->text == kDirectiveUndef) + if (token->text == kDirectiveUndef) return DIRECTIVE_UNDEF; - else if (token->text == kDirectiveIf) + if (token->text == kDirectiveIf) return DIRECTIVE_IF; - else if (token->text == kDirectiveIfdef) + if (token->text == kDirectiveIfdef) return DIRECTIVE_IFDEF; - else if (token->text == kDirectiveIfndef) + if (token->text == kDirectiveIfndef) return DIRECTIVE_IFNDEF; - else if (token->text == kDirectiveElse) + if (token->text == kDirectiveElse) return DIRECTIVE_ELSE; - else if (token->text == kDirectiveElif) + if (token->text == kDirectiveElif) return DIRECTIVE_ELIF; - else if (token->text == kDirectiveEndif) + if (token->text == kDirectiveEndif) return DIRECTIVE_ENDIF; - else if (token->text == kDirectiveError) + if (token->text == kDirectiveError) return DIRECTIVE_ERROR; - else if (token->text == kDirectivePragma) + if (token->text == kDirectivePragma) return DIRECTIVE_PRAGMA; - else if (token->text == kDirectiveExtension) + if (token->text == kDirectiveExtension) return DIRECTIVE_EXTENSION; - else if (token->text == kDirectiveVersion) + if (token->text == kDirectiveVersion) return DIRECTIVE_VERSION; - else if (token->text == kDirectiveLine) + if (token->text == kDirectiveLine) return DIRECTIVE_LINE; return DIRECTIVE_NONE; } -static bool isConditionalDirective(DirectiveType directive) +bool isConditionalDirective(DirectiveType directive) { switch (directive) { @@ -103,12 +102,12 @@ static bool isConditionalDirective(DirectiveType directive) } // Returns true if the token represents End Of Directive. -static bool isEOD(const pp::Token* token) +bool isEOD(const pp::Token *token) { return (token->type == '\n') || (token->type == pp::Token::LAST); } -static void skipUntilEOD(pp::Lexer* lexer, pp::Token* token) +void skipUntilEOD(pp::Lexer *lexer, pp::Token *token) { while(!isEOD(token)) { @@ -116,7 +115,7 @@ static void skipUntilEOD(pp::Lexer* lexer, pp::Token* token) } } -static bool isMacroNameReserved(const std::string& name) +bool isMacroNameReserved(const std::string &name) { // Names prefixed with "GL_" are reserved. if (name.substr(0, 3) == "GL_") @@ -129,30 +128,32 @@ static bool isMacroNameReserved(const std::string& name) return false; } -static bool isMacroPredefined(const std::string& name, - const pp::MacroSet& macroSet) +bool isMacroPredefined(const std::string &name, + const pp::MacroSet ¯oSet) { pp::MacroSet::const_iterator iter = macroSet.find(name); return iter != macroSet.end() ? iter->second.predefined : false; } +} // namespace anonymous + namespace pp { class DefinedParser : public Lexer { public: - DefinedParser(Lexer* lexer, - const MacroSet* macroSet, - Diagnostics* diagnostics) : - mLexer(lexer), - mMacroSet(macroSet), - mDiagnostics(diagnostics) + DefinedParser(Lexer *lexer, + const MacroSet *macroSet, + Diagnostics *diagnostics) + : mLexer(lexer), + mMacroSet(macroSet), + mDiagnostics(diagnostics) { } protected: - virtual void lex(Token* token) + virtual void lex(Token *token) { static const std::string kDefined("defined"); @@ -199,24 +200,24 @@ class DefinedParser : public Lexer } private: - Lexer* mLexer; - const MacroSet* mMacroSet; - Diagnostics* mDiagnostics; + Lexer *mLexer; + const MacroSet *mMacroSet; + Diagnostics *mDiagnostics; }; -DirectiveParser::DirectiveParser(Tokenizer* tokenizer, - MacroSet* macroSet, - Diagnostics* diagnostics, - DirectiveHandler* directiveHandler) : - mPastFirstStatement(false), - mTokenizer(tokenizer), - mMacroSet(macroSet), - mDiagnostics(diagnostics), - mDirectiveHandler(directiveHandler) +DirectiveParser::DirectiveParser(Tokenizer *tokenizer, + MacroSet *macroSet, + Diagnostics *diagnostics, + DirectiveHandler *directiveHandler) + : mPastFirstStatement(false), + mTokenizer(tokenizer), + mMacroSet(macroSet), + mDiagnostics(diagnostics), + mDirectiveHandler(directiveHandler) { } -void DirectiveParser::lex(Token* token) +void DirectiveParser::lex(Token *token) { do { @@ -232,19 +233,20 @@ void DirectiveParser::lex(Token* token) { if (!mConditionalStack.empty()) { - const ConditionalBlock& block = mConditionalStack.back(); + const ConditionalBlock &block = mConditionalStack.back(); mDiagnostics->report(Diagnostics::PP_CONDITIONAL_UNTERMINATED, block.location, block.type); } break; } - } while (skipping() || (token->type == '\n')); + } + while (skipping() || (token->type == '\n')); mPastFirstStatement = true; } -void DirectiveParser::parseDirective(Token* token) +void DirectiveParser::parseDirective(Token *token) { assert(token->type == Token::PP_HASH); @@ -324,7 +326,7 @@ void DirectiveParser::parseDirective(Token* token) } } -void DirectiveParser::parseDefine(Token* token) +void DirectiveParser::parseDefine(Token *token) { assert(getDirective(token) == DIRECTIVE_DEFINE); @@ -357,14 +359,16 @@ void DirectiveParser::parseDefine(Token* token) { // Function-like macro. Collect arguments. macro.type = Macro::kTypeFunc; - do { + do + { mTokenizer->lex(token); if (token->type != Token::IDENTIFIER) break; macro.parameters.push_back(token->text); mTokenizer->lex(token); // Get ','. - } while (token->type == ','); + } + while (token->type == ','); if (token->type != ')') { @@ -404,7 +408,7 @@ void DirectiveParser::parseDefine(Token* token) mMacroSet->insert(std::make_pair(macro.name, macro)); } -void DirectiveParser::parseUndef(Token* token) +void DirectiveParser::parseUndef(Token *token) { assert(getDirective(token) == DIRECTIVE_UNDEF); @@ -433,25 +437,25 @@ void DirectiveParser::parseUndef(Token* token) mTokenizer->lex(token); } -void DirectiveParser::parseIf(Token* token) +void DirectiveParser::parseIf(Token *token) { assert(getDirective(token) == DIRECTIVE_IF); parseConditionalIf(token); } -void DirectiveParser::parseIfdef(Token* token) +void DirectiveParser::parseIfdef(Token *token) { assert(getDirective(token) == DIRECTIVE_IFDEF); parseConditionalIf(token); } -void DirectiveParser::parseIfndef(Token* token) +void DirectiveParser::parseIfndef(Token *token) { assert(getDirective(token) == DIRECTIVE_IFNDEF); parseConditionalIf(token); } -void DirectiveParser::parseElse(Token* token) +void DirectiveParser::parseElse(Token *token) { assert(getDirective(token) == DIRECTIVE_ELSE); @@ -463,7 +467,7 @@ void DirectiveParser::parseElse(Token* token) return; } - ConditionalBlock& block = mConditionalStack.back(); + ConditionalBlock &block = mConditionalStack.back(); if (block.skipBlock) { // No diagnostics. Just skip the whole line. @@ -492,7 +496,7 @@ void DirectiveParser::parseElse(Token* token) } } -void DirectiveParser::parseElif(Token* token) +void DirectiveParser::parseElif(Token *token) { assert(getDirective(token) == DIRECTIVE_ELIF); @@ -504,7 +508,7 @@ void DirectiveParser::parseElif(Token* token) return; } - ConditionalBlock& block = mConditionalStack.back(); + ConditionalBlock &block = mConditionalStack.back(); if (block.skipBlock) { // No diagnostics. Just skip the whole line. @@ -532,7 +536,7 @@ void DirectiveParser::parseElif(Token* token) block.foundValidGroup = expression != 0; } -void DirectiveParser::parseEndif(Token* token) +void DirectiveParser::parseEndif(Token *token) { assert(getDirective(token) == DIRECTIVE_ENDIF); @@ -556,7 +560,7 @@ void DirectiveParser::parseEndif(Token* token) } } -void DirectiveParser::parseError(Token* token) +void DirectiveParser::parseError(Token *token) { assert(getDirective(token) == DIRECTIVE_ERROR); @@ -571,7 +575,7 @@ void DirectiveParser::parseError(Token* token) } // Parses pragma of form: #pragma name[(value)]. -void DirectiveParser::parsePragma(Token* token) +void DirectiveParser::parsePragma(Token *token) { assert(getDirective(token) == DIRECTIVE_PRAGMA); @@ -627,7 +631,7 @@ void DirectiveParser::parsePragma(Token* token) } } -void DirectiveParser::parseExtension(Token* token) +void DirectiveParser::parseExtension(Token *token) { assert(getDirective(token) == DIRECTIVE_EXTENSION); @@ -694,7 +698,7 @@ void DirectiveParser::parseExtension(Token* token) mDirectiveHandler->handleExtension(token->location, name, behavior); } -void DirectiveParser::parseVersion(Token* token) +void DirectiveParser::parseVersion(Token *token) { assert(getDirective(token) == DIRECTIVE_VERSION); @@ -708,7 +712,9 @@ void DirectiveParser::parseVersion(Token* token) enum State { - VERSION_NUMBER + VERSION_NUMBER, + VERSION_PROFILE, + VERSION_ENDLINE }; bool valid = true; @@ -716,12 +722,12 @@ void DirectiveParser::parseVersion(Token* token) int state = VERSION_NUMBER; mTokenizer->lex(token); - while ((token->type != '\n') && (token->type != Token::LAST)) + while (valid && (token->type != '\n') && (token->type != Token::LAST)) { - switch (state++) + switch (state) { case VERSION_NUMBER: - if (valid && (token->type != Token::CONST_INT)) + if (token->type != Token::CONST_INT) { mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_NUMBER, token->location, token->text); @@ -733,29 +739,44 @@ void DirectiveParser::parseVersion(Token* token) token->location, token->text); valid = false; } - break; - default: if (valid) { - mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, + state = (version < 300) ? VERSION_ENDLINE : VERSION_PROFILE; + } + break; + case VERSION_PROFILE: + if (token->type != Token::IDENTIFIER || token->text != "es") + { + mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE, token->location, token->text); valid = false; } + state = VERSION_ENDLINE; + break; + default: + mDiagnostics->report(Diagnostics::PP_UNEXPECTED_TOKEN, + token->location, token->text); + valid = false; break; } + mTokenizer->lex(token); } - if (valid && (state != VERSION_NUMBER + 1)) + + if (valid && (state != VERSION_ENDLINE)) { mDiagnostics->report(Diagnostics::PP_INVALID_VERSION_DIRECTIVE, token->location, token->text); valid = false; } + if (valid) + { mDirectiveHandler->handleVersion(token->location, version); + } } -void DirectiveParser::parseLine(Token* token) +void DirectiveParser::parseLine(Token *token) { assert(getDirective(token) == DIRECTIVE_LINE); @@ -824,19 +845,21 @@ void DirectiveParser::parseLine(Token* token) if (valid) { mTokenizer->setLineNumber(line); - if (state == FILE_NUMBER + 1) mTokenizer->setFileNumber(file); + if (state == FILE_NUMBER + 1) + mTokenizer->setFileNumber(file); } } bool DirectiveParser::skipping() const { - if (mConditionalStack.empty()) return false; + if (mConditionalStack.empty()) + return false; const ConditionalBlock& block = mConditionalStack.back(); return block.skipBlock || block.skipGroup; } -void DirectiveParser::parseConditionalIf(Token* token) +void DirectiveParser::parseConditionalIf(Token *token) { ConditionalBlock block; block.type = token->text; @@ -877,7 +900,7 @@ void DirectiveParser::parseConditionalIf(Token* token) mConditionalStack.push_back(block); } -int DirectiveParser::parseExpressionIf(Token* token) +int DirectiveParser::parseExpressionIf(Token *token) { assert((getDirective(token) == DIRECTIVE_IF) || (getDirective(token) == DIRECTIVE_ELIF)); @@ -901,7 +924,7 @@ int DirectiveParser::parseExpressionIf(Token* token) return expression; } -int DirectiveParser::parseExpressionIfdef(Token* token) +int DirectiveParser::parseExpressionIfdef(Token *token) { assert((getDirective(token) == DIRECTIVE_IFDEF) || (getDirective(token) == DIRECTIVE_IFNDEF)); diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h index 8a7f0072ba..335091781c 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h @@ -22,35 +22,35 @@ class Tokenizer; class DirectiveParser : public Lexer { public: - DirectiveParser(Tokenizer* tokenizer, - MacroSet* macroSet, - Diagnostics* diagnostics, - DirectiveHandler* directiveHandler); + DirectiveParser(Tokenizer *tokenizer, + MacroSet *macroSet, + Diagnostics *diagnostics, + DirectiveHandler *directiveHandler); - virtual void lex(Token* token); + virtual void lex(Token *token); private: PP_DISALLOW_COPY_AND_ASSIGN(DirectiveParser); - void parseDirective(Token* token); - void parseDefine(Token* token); - void parseUndef(Token* token); - void parseIf(Token* token); - void parseIfdef(Token* token); - void parseIfndef(Token* token); - void parseElse(Token* token); - void parseElif(Token* token); - void parseEndif(Token* token); - void parseError(Token* token); - void parsePragma(Token* token); - void parseExtension(Token* token); - void parseVersion(Token* token); - void parseLine(Token* token); + void parseDirective(Token *token); + void parseDefine(Token *token); + void parseUndef(Token *token); + void parseIf(Token *token); + void parseIfdef(Token *token); + void parseIfndef(Token *token); + void parseElse(Token *token); + void parseElif(Token *token); + void parseEndif(Token *token); + void parseError(Token *token); + void parsePragma(Token *token); + void parseExtension(Token *token); + void parseVersion(Token *token); + void parseLine(Token *token); bool skipping() const; - void parseConditionalIf(Token* token); - int parseExpressionIf(Token* token); - int parseExpressionIfdef(Token* token); + void parseConditionalIf(Token *token); + int parseExpressionIf(Token *token); + int parseExpressionIfdef(Token *token); struct ConditionalBlock { @@ -61,20 +61,20 @@ class DirectiveParser : public Lexer bool foundValidGroup; bool foundElseGroup; - ConditionalBlock() : - skipBlock(false), - skipGroup(false), - foundValidGroup(false), - foundElseGroup(false) + ConditionalBlock() + : skipBlock(false), + skipGroup(false), + foundValidGroup(false), + foundElseGroup(false) { } }; bool mPastFirstStatement; std::vector mConditionalStack; - Tokenizer* mTokenizer; - MacroSet* mMacroSet; - Diagnostics* mDiagnostics; - DirectiveHandler* mDirectiveHandler; + Tokenizer *mTokenizer; + MacroSet *mMacroSet; + Diagnostics *mDiagnostics; + DirectiveHandler *mDirectiveHandler; }; } // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h index 092d059413..f040cb01fa 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h @@ -19,15 +19,15 @@ struct Token; class ExpressionParser { public: - ExpressionParser(Lexer* lexer, Diagnostics* diagnostics); + ExpressionParser(Lexer *lexer, Diagnostics *diagnostics); - bool parse(Token* token, int* result); + bool parse(Token *token, int *result); private: PP_DISALLOW_COPY_AND_ASSIGN(ExpressionParser); - Lexer* mLexer; - Diagnostics* mDiagnostics; + Lexer *mLexer; + Diagnostics *mDiagnostics; }; } // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y index 9fa0f0bf80..662a31b650 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y +++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y @@ -195,15 +195,14 @@ expression %% -int yylex(YYSTYPE* lvalp, Context* context) +int yylex(YYSTYPE *lvalp, Context *context) { int type = 0; - pp::Token* token = context->token; + pp::Token *token = context->token; switch (token->type) { - case pp::Token::CONST_INT: - { + case pp::Token::CONST_INT: { unsigned int val = 0; if (!token->uValue(&val)) { @@ -214,39 +213,59 @@ int yylex(YYSTYPE* lvalp, Context* context) type = TOK_CONST_INT; break; } - case pp::Token::OP_OR: type = TOK_OP_OR; break; - case pp::Token::OP_AND: type = TOK_OP_AND; break; - case pp::Token::OP_NE: type = TOK_OP_NE; break; - case pp::Token::OP_EQ: type = TOK_OP_EQ; break; - case pp::Token::OP_GE: type = TOK_OP_GE; break; - case pp::Token::OP_LE: type = TOK_OP_LE; break; - case pp::Token::OP_RIGHT: type = TOK_OP_RIGHT; break; - case pp::Token::OP_LEFT: type = TOK_OP_LEFT; break; - case '|': type = '|'; break; - case '^': type = '^'; break; - case '&': type = '&'; break; - case '>': type = '>'; break; - case '<': type = '<'; break; - case '-': type = '-'; break; - case '+': type = '+'; break; - case '%': type = '%'; break; - case '/': type = '/'; break; - case '*': type = '*'; break; - case '!': type = '!'; break; - case '~': type = '~'; break; - case '(': type = '('; break; - case ')': type = ')'; break; + case pp::Token::OP_OR: + type = TOK_OP_OR; + break; + case pp::Token::OP_AND: + type = TOK_OP_AND; + break; + case pp::Token::OP_NE: + type = TOK_OP_NE; + break; + case pp::Token::OP_EQ: + type = TOK_OP_EQ; + break; + case pp::Token::OP_GE: + type = TOK_OP_GE; + break; + case pp::Token::OP_LE: + type = TOK_OP_LE; + break; + case pp::Token::OP_RIGHT: + type = TOK_OP_RIGHT; + break; + case pp::Token::OP_LEFT: + type = TOK_OP_LEFT; + break; + case '|': + case '^': + case '&': + case '>': + case '<': + case '-': + case '+': + case '%': + case '/': + case '*': + case '!': + case '~': + case '(': + case ')': + type = token->type; + break; - default: break; + default: + break; } // Advance to the next token if the current one is valid. - if (type != 0) context->lexer->lex(token); + if (type != 0) + context->lexer->lex(token); return type; } -void yyerror(Context* context, const char* reason) +void yyerror(Context *context, const char *reason) { context->diagnostics->report(pp::Diagnostics::PP_INVALID_EXPRESSION, context->token->location, @@ -255,13 +274,13 @@ void yyerror(Context* context, const char* reason) namespace pp { -ExpressionParser::ExpressionParser(Lexer* lexer, Diagnostics* diagnostics) : - mLexer(lexer), - mDiagnostics(diagnostics) +ExpressionParser::ExpressionParser(Lexer *lexer, Diagnostics *diagnostics) + : mLexer(lexer), + mDiagnostics(diagnostics) { } -bool ExpressionParser::parse(Token* token, int* result) +bool ExpressionParser::parse(Token *token, int *result) { Context context; context.diagnostics = mDiagnostics; diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Input.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Input.cpp index b4d970a97d..f9910a6cc3 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Input.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/Input.cpp @@ -17,7 +17,7 @@ Input::Input() : mCount(0), mString(0) { } -Input::Input(size_t count, const char* const string[], const int length[]) : +Input::Input(size_t count, const char *const string[], const int length[]) : mCount(count), mString(string) { @@ -29,7 +29,7 @@ Input::Input(size_t count, const char* const string[], const int length[]) : } } -size_t Input::read(char* buf, size_t maxSize) +size_t Input::read(char *buf, size_t maxSize) { size_t nRead = 0; while ((nRead < maxSize) && (mReadLoc.sIndex < mCount)) diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Input.h b/src/3rdparty/angle/src/compiler/preprocessor/Input.h index 14b7597cb4..2ac4f0c170 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Input.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Input.h @@ -18,27 +18,40 @@ class Input { public: Input(); - Input(size_t count, const char* const string[], const int length[]); + Input(size_t count, const char *const string[], const int length[]); - size_t count() const { return mCount; } - const char* string(size_t index) const { return mString[index]; } - size_t length(size_t index) const { return mLength[index]; } + size_t count() const + { + return mCount; + } + const char *string(size_t index) const + { + return mString[index]; + } + size_t length(size_t index) const + { + return mLength[index]; + } - size_t read(char* buf, size_t maxSize); + size_t read(char *buf, size_t maxSize); struct Location { size_t sIndex; // String index; size_t cIndex; // Char index. - Location() : sIndex(0), cIndex(0) { } + Location() + : sIndex(0), + cIndex(0) + { + } }; - const Location& readLoc() const { return mReadLoc; } + const Location &readLoc() const { return mReadLoc; } private: // Input. size_t mCount; - const char* const* mString; + const char * const *mString; std::vector mLength; Location mReadLoc; diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h index eb85cea873..d42d3db7e0 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h @@ -17,7 +17,7 @@ class Lexer public: virtual ~Lexer(); - virtual void lex(Token* token) = 0; + virtual void lex(Token *token) = 0; }; } // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp index b2e3088e32..13cb14e3dc 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/Macro.cpp @@ -11,7 +11,7 @@ namespace pp { -bool Macro::equals(const Macro& other) const +bool Macro::equals(const Macro &other) const { return (type == other.type) && (name == other.name) && diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Macro.h b/src/3rdparty/angle/src/compiler/preprocessor/Macro.h index 7ec0149116..b77e7bc15c 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Macro.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Macro.h @@ -26,8 +26,13 @@ struct Macro typedef std::vector Parameters; typedef std::vector Replacements; - Macro() : predefined(false), disabled(false), type(kTypeObj) { } - bool equals(const Macro& other) const; + Macro() + : predefined(false), + disabled(false), + type(kTypeObj) + { + } + bool equals(const Macro &other) const; bool predefined; mutable bool disabled; diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp index b789260af9..d7e0c83465 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.cpp @@ -20,13 +20,13 @@ class TokenLexer : public Lexer public: typedef std::vector TokenVector; - TokenLexer(TokenVector* tokens) + TokenLexer(TokenVector *tokens) { tokens->swap(mTokens); mIter = mTokens.begin(); } - virtual void lex(Token* token) + virtual void lex(Token *token) { if (mIter == mTokens.end()) { @@ -46,12 +46,12 @@ class TokenLexer : public Lexer TokenVector::const_iterator mIter; }; -MacroExpander::MacroExpander(Lexer* lexer, - MacroSet* macroSet, - Diagnostics* diagnostics) : - mLexer(lexer), - mMacroSet(macroSet), - mDiagnostics(diagnostics) +MacroExpander::MacroExpander(Lexer *lexer, + MacroSet *macroSet, + Diagnostics *diagnostics) + : mLexer(lexer), + mMacroSet(macroSet), + mDiagnostics(diagnostics) { } @@ -63,7 +63,7 @@ MacroExpander::~MacroExpander() } } -void MacroExpander::lex(Token* token) +void MacroExpander::lex(Token *token) { while (true) { @@ -97,7 +97,7 @@ void MacroExpander::lex(Token* token) } } -void MacroExpander::getToken(Token* token) +void MacroExpander::getToken(Token *token) { if (mReserveToken.get()) { @@ -122,11 +122,11 @@ void MacroExpander::getToken(Token* token) } } -void MacroExpander::ungetToken(const Token& token) +void MacroExpander::ungetToken(const Token &token) { if (!mContextStack.empty()) { - MacroContext* context = mContextStack.back(); + MacroContext *context = mContextStack.back(); context->unget(); assert(context->replacements[context->index] == token); } @@ -148,7 +148,7 @@ bool MacroExpander::isNextTokenLeftParen() return lparen; } -bool MacroExpander::pushMacro(const Macro& macro, const Token& identifier) +bool MacroExpander::pushMacro(const Macro ¯o, const Token &identifier) { assert(!macro.disabled); assert(!identifier.expansionDisabled()); @@ -162,7 +162,7 @@ bool MacroExpander::pushMacro(const Macro& macro, const Token& identifier) // Macro is disabled for expansion until it is popped off the stack. macro.disabled = true; - MacroContext* context = new MacroContext; + MacroContext *context = new MacroContext; context->macro = ¯o; context->replacements.swap(replacements); mContextStack.push_back(context); @@ -173,7 +173,7 @@ void MacroExpander::popMacro() { assert(!mContextStack.empty()); - MacroContext* context = mContextStack.back(); + MacroContext *context = mContextStack.back(); mContextStack.pop_back(); assert(context->empty()); @@ -182,9 +182,9 @@ void MacroExpander::popMacro() delete context; } -bool MacroExpander::expandMacro(const Macro& macro, - const Token& identifier, - std::vector* replacements) +bool MacroExpander::expandMacro(const Macro ¯o, + const Token &identifier, + std::vector *replacements) { replacements->clear(); if (macro.type == Macro::kTypeObj) @@ -239,9 +239,9 @@ bool MacroExpander::expandMacro(const Macro& macro, return true; } -bool MacroExpander::collectMacroArgs(const Macro& macro, - const Token& identifier, - std::vector* args) +bool MacroExpander::collectMacroArgs(const Macro ¯o, + const Token &identifier, + std::vector *args) { Token token; getToken(&token); @@ -276,7 +276,8 @@ bool MacroExpander::collectMacroArgs(const Macro& macro, // The individual arguments are separated by comma tokens, but // the comma tokens between matching inner parentheses do not // seperate arguments. - if (openParens == 1) args->push_back(MacroArg()); + if (openParens == 1) + args->push_back(MacroArg()); isArg = openParens != 1; break; default: @@ -285,14 +286,15 @@ bool MacroExpander::collectMacroArgs(const Macro& macro, } if (isArg) { - MacroArg& arg = args->back(); + MacroArg &arg = args->back(); // Initial whitespace is not part of the argument. - if (arg.empty()) token.setHasLeadingSpace(false); + if (arg.empty()) + token.setHasLeadingSpace(false); arg.push_back(token); } } - const Macro::Parameters& params = macro.parameters; + const Macro::Parameters ¶ms = macro.parameters; // If there is only one empty argument, it is equivalent to no argument. if (params.empty() && (args->size() == 1) && args->front().empty()) { @@ -313,7 +315,7 @@ bool MacroExpander::collectMacroArgs(const Macro& macro, // inserted into the macro body. for (std::size_t i = 0; i < args->size(); ++i) { - MacroArg& arg = args->at(i); + MacroArg &arg = args->at(i); TokenLexer lexer(&arg); MacroExpander expander(&lexer, mMacroSet, mDiagnostics); @@ -328,13 +330,13 @@ bool MacroExpander::collectMacroArgs(const Macro& macro, return true; } -void MacroExpander::replaceMacroParams(const Macro& macro, - const std::vector& args, - std::vector* replacements) +void MacroExpander::replaceMacroParams(const Macro ¯o, + const std::vector &args, + std::vector *replacements) { for (std::size_t i = 0; i < macro.replacements.size(); ++i) { - const Token& repl = macro.replacements[i]; + const Token &repl = macro.replacements[i]; if (repl.type != Token::IDENTIFIER) { replacements->push_back(repl); @@ -353,7 +355,7 @@ void MacroExpander::replaceMacroParams(const Macro& macro, } std::size_t iArg = std::distance(macro.parameters.begin(), iter); - const MacroArg& arg = args[iArg]; + const MacroArg &arg = args[iArg]; if (arg.empty()) { continue; diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h index 21b67571f1..d4fd091786 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h @@ -23,51 +23,65 @@ class Diagnostics; class MacroExpander : public Lexer { public: - MacroExpander(Lexer* lexer, MacroSet* macroSet, Diagnostics* diagnostics); + MacroExpander(Lexer *lexer, MacroSet *macroSet, Diagnostics *diagnostics); virtual ~MacroExpander(); - virtual void lex(Token* token); + virtual void lex(Token *token); private: PP_DISALLOW_COPY_AND_ASSIGN(MacroExpander); - void getToken(Token* token); - void ungetToken(const Token& token); + void getToken(Token *token); + void ungetToken(const Token &token); bool isNextTokenLeftParen(); - bool pushMacro(const Macro& macro, const Token& identifier); + bool pushMacro(const Macro ¯o, const Token &identifier); void popMacro(); - bool expandMacro(const Macro& macro, - const Token& identifier, - std::vector* replacements); + bool expandMacro(const Macro ¯o, + const Token &identifier, + std::vector *replacements); typedef std::vector MacroArg; - bool collectMacroArgs(const Macro& macro, - const Token& identifier, - std::vector* args); - void replaceMacroParams(const Macro& macro, - const std::vector& args, - std::vector* replacements); + bool collectMacroArgs(const Macro ¯o, + const Token &identifier, + std::vector *args); + void replaceMacroParams(const Macro ¯o, + const std::vector &args, + std::vector *replacements); struct MacroContext { - const Macro* macro; + const Macro *macro; std::size_t index; std::vector replacements; - MacroContext() : macro(0), index(0) { } - bool empty() const { return index == replacements.size(); } - const Token& get() { return replacements[index++]; } - void unget() { assert(index > 0); --index; } + MacroContext() + : macro(0), + index(0) + { + } + bool empty() const + { + return index == replacements.size(); + } + const Token &get() + { + return replacements[index++]; + } + void unget() + { + assert(index > 0); + --index; + } }; - Lexer* mLexer; - MacroSet* mMacroSet; - Diagnostics* mDiagnostics; + Lexer *mLexer; + MacroSet *mMacroSet; + Diagnostics *mDiagnostics; std::auto_ptr mReserveToken; - std::vector mContextStack; + std::vector mContextStack; }; } // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp index 580ffba459..3522fa1abb 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.cpp @@ -21,24 +21,24 @@ namespace pp struct PreprocessorImpl { - Diagnostics* diagnostics; + Diagnostics *diagnostics; MacroSet macroSet; Tokenizer tokenizer; DirectiveParser directiveParser; MacroExpander macroExpander; - PreprocessorImpl(Diagnostics* diag, - DirectiveHandler* directiveHandler) : - diagnostics(diag), - tokenizer(diag), - directiveParser(&tokenizer, ¯oSet, diag, directiveHandler), - macroExpander(&directiveParser, ¯oSet, diag) + PreprocessorImpl(Diagnostics *diag, + DirectiveHandler *directiveHandler) + : diagnostics(diag), + tokenizer(diag), + directiveParser(&tokenizer, ¯oSet, diag, directiveHandler), + macroExpander(&directiveParser, ¯oSet, diag) { } }; -Preprocessor::Preprocessor(Diagnostics* diagnostics, - DirectiveHandler* directiveHandler) +Preprocessor::Preprocessor(Diagnostics *diagnostics, + DirectiveHandler *directiveHandler) { mImpl = new PreprocessorImpl(diagnostics, directiveHandler); } @@ -49,7 +49,7 @@ Preprocessor::~Preprocessor() } bool Preprocessor::init(size_t count, - const char* const string[], + const char * const string[], const int length[]) { static const int kGLSLVersion = 100; @@ -63,7 +63,7 @@ bool Preprocessor::init(size_t count, return mImpl->tokenizer.init(count, string, length); } -void Preprocessor::predefineMacro(const char* name, int value) +void Preprocessor::predefineMacro(const char *name, int value) { std::ostringstream stream; stream << value; @@ -81,12 +81,7 @@ void Preprocessor::predefineMacro(const char* name, int value) mImpl->macroSet[name] = macro; } -void Preprocessor::setMaxTokenLength(size_t maxLength) -{ - mImpl->tokenizer.setMaxTokenLength(maxLength); -} - -void Preprocessor::lex(Token* token) +void Preprocessor::lex(Token *token) { bool validToken = false; while (!validToken) @@ -115,5 +110,9 @@ void Preprocessor::lex(Token* token) } } -} // namespace pp +void Preprocessor::setMaxTokenSize(size_t maxTokenSize) +{ + mImpl->tokenizer.setMaxTokenSize(maxTokenSize); +} +} // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h index 9a90d79a1a..0a55f1c9c1 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h @@ -22,7 +22,7 @@ struct Token; class Preprocessor { public: - Preprocessor(Diagnostics* diagnostics, DirectiveHandler* directiveHandler); + Preprocessor(Diagnostics *diagnostics, DirectiveHandler *directiveHandler); ~Preprocessor(); // count: specifies the number of elements in the string and length arrays. @@ -34,22 +34,19 @@ class Preprocessor // Each element in the length array may contain the length of the // corresponding string or a value less than 0 to indicate that the string // is null terminated. - bool init(size_t count, const char* const string[], const int length[]); + bool init(size_t count, const char * const string[], const int length[]); // Adds a pre-defined macro. - void predefineMacro(const char* name, int value); - // Sets maximum allowed token length. - // If token length exceeds this limit, - // the token text will be truncated to the given maximum length, and - // TOKEN_TOO_LONG diagnostic will be generated. - // The maximum length defaults to 256. - void setMaxTokenLength(size_t maxLength); + void predefineMacro(const char *name, int value); - void lex(Token* token); + void lex(Token *token); + + // Set maximum preprocessor token size + void setMaxTokenSize(size_t maxTokenSize); private: PP_DISALLOW_COPY_AND_ASSIGN(Preprocessor); - PreprocessorImpl* mImpl; + PreprocessorImpl *mImpl; }; } // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h b/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h index 6982613ac7..d4c1a5e178 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h @@ -12,10 +12,18 @@ namespace pp struct SourceLocation { - SourceLocation() : file(0), line(0) { } - SourceLocation(int f, int l) : file(f), line(l) { } + SourceLocation() + : file(0), + line(0) + { + } + SourceLocation(int f, int l) + : file(f), + line(l) + { + } - bool equals(const SourceLocation& other) const + bool equals(const SourceLocation &other) const { return (file == other.file) && (line == other.line); } @@ -24,12 +32,12 @@ struct SourceLocation int line; }; -inline bool operator==(const SourceLocation& lhs, const SourceLocation& rhs) +inline bool operator==(const SourceLocation &lhs, const SourceLocation &rhs) { return lhs.equals(rhs); } -inline bool operator!=(const SourceLocation& lhs, const SourceLocation& rhs) +inline bool operator!=(const SourceLocation &lhs, const SourceLocation &rhs) { return !lhs.equals(rhs); } diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Token.cpp b/src/3rdparty/angle/src/compiler/preprocessor/Token.cpp index 67f50aa32c..d102654747 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Token.cpp +++ b/src/3rdparty/angle/src/compiler/preprocessor/Token.cpp @@ -21,7 +21,7 @@ void Token::reset() text.clear(); } -bool Token::equals(const Token& other) const +bool Token::equals(const Token &other) const { return (type == other.type) && (flags == other.flags) && @@ -53,25 +53,25 @@ void Token::setExpansionDisabled(bool disable) flags &= ~EXPANSION_DISABLED; } -bool Token::iValue(int* value) const +bool Token::iValue(int *value) const { assert(type == CONST_INT); return numeric_lex_int(text, value); } -bool Token::uValue(unsigned int* value) const +bool Token::uValue(unsigned int *value) const { assert(type == CONST_INT); return numeric_lex_int(text, value); } -bool Token::fValue(float* value) const +bool Token::fValue(float *value) const { assert(type == CONST_FLOAT); return numeric_lex_float(text, value); } -std::ostream& operator<<(std::ostream& out, const Token& token) +std::ostream &operator<<(std::ostream &out, const Token &token) { if (token.hasLeadingSpace()) out << " "; diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Token.h b/src/3rdparty/angle/src/compiler/preprocessor/Token.h index 8b553aecb6..8832e279c7 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Token.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Token.h @@ -62,27 +62,40 @@ struct Token EXPANSION_DISABLED = 1 << 2 }; - Token() : type(0), flags(0) { } + Token() + : type(0), + flags(0) + { + } void reset(); - bool equals(const Token& other) const; + bool equals(const Token &other) const; // Returns true if this is the first token on line. // It disregards any leading whitespace. - bool atStartOfLine() const { return (flags & AT_START_OF_LINE) != 0; } + bool atStartOfLine() const + { + return (flags & AT_START_OF_LINE) != 0; + } void setAtStartOfLine(bool start); - bool hasLeadingSpace() const { return (flags & HAS_LEADING_SPACE) != 0; } + bool hasLeadingSpace() const + { + return (flags & HAS_LEADING_SPACE) != 0; + } void setHasLeadingSpace(bool space); - bool expansionDisabled() const { return (flags & EXPANSION_DISABLED) != 0; } + bool expansionDisabled() const + { + return (flags & EXPANSION_DISABLED) != 0; + } void setExpansionDisabled(bool disable); // Converts text into numeric value for CONST_INT and CONST_FLOAT token. // Returns false if the parsed value cannot fit into an int or float. - bool iValue(int* value) const; - bool uValue(unsigned int* value) const; - bool fValue(float* value) const; + bool iValue(int *value) const; + bool uValue(unsigned int *value) const; + bool fValue(float *value) const; int type; unsigned int flags; @@ -90,17 +103,17 @@ struct Token std::string text; }; -inline bool operator==(const Token& lhs, const Token& rhs) +inline bool operator==(const Token &lhs, const Token &rhs) { return lhs.equals(rhs); } -inline bool operator!=(const Token& lhs, const Token& rhs) +inline bool operator!=(const Token &lhs, const Token &rhs) { return !lhs.equals(rhs); } -extern std::ostream& operator<<(std::ostream& out, const Token& token); +extern std::ostream &operator<<(std::ostream &out, const Token &token); } // namepsace pp #endif // COMPILER_PREPROCESSOR_TOKEN_H_ diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h index 9d131f865a..07ad93da05 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -21,7 +21,7 @@ class Tokenizer : public Lexer public: struct Context { - Diagnostics* diagnostics; + Diagnostics *diagnostics; Input input; // The location where yytext points to. Token location should track @@ -33,25 +33,25 @@ class Tokenizer : public Lexer bool lineStart; }; - Tokenizer(Diagnostics* diagnostics); + Tokenizer(Diagnostics *diagnostics); ~Tokenizer(); - bool init(size_t count, const char* const string[], const int length[]); + bool init(size_t count, const char * const string[], const int length[]); - void setMaxTokenLength(size_t maxLength) { mMaxTokenLength = maxLength; } void setFileNumber(int file); void setLineNumber(int line); + void setMaxTokenSize(size_t maxTokenSize); - virtual void lex(Token* token); + virtual void lex(Token *token); private: PP_DISALLOW_COPY_AND_ASSIGN(Tokenizer); bool initScanner(); void destroyScanner(); - void* mHandle; // Scanner handle. + void *mHandle; // Scanner handle. Context mContext; // Scanner extra. - size_t mMaxTokenLength; + size_t mMaxTokenSize; // Maximum token size }; } // namespace pp diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l index f1380b26b7..2a77b905a4 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l +++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l @@ -1,6 +1,6 @@ /* // -// Copyright (c) 2002-2013 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. // @@ -14,7 +14,7 @@ IF YOU MODIFY THIS FILE YOU ALSO NEED TO RUN generate_parser.sh. %top{ // -// Copyright (c) 2011-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2011-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -78,9 +78,9 @@ NEWLINE \n|\r|\r\n IDENTIFIER [_a-zA-Z][_a-zA-Z0-9]* PUNCTUATOR [][<>(){}.+-/*%^|&~=!:;,?] -DECIMAL_CONSTANT [1-9][0-9]* -OCTAL_CONSTANT 0[0-7]* -HEXADECIMAL_CONSTANT 0[xX][0-9a-fA-F]+ +DECIMAL_CONSTANT [1-9][0-9]*[uU]? +OCTAL_CONSTANT 0[0-7]*[uU]? +HEXADECIMAL_CONSTANT 0[xX][0-9a-fA-F]+[uU]? DIGIT [0-9] EXPONENT_PART [eE][+-]?{DIGIT}+ @@ -114,12 +114,12 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".") return pp::Token::IDENTIFIER; } -{DECIMAL_CONSTANT}|{OCTAL_CONSTANT}|{HEXADECIMAL_CONSTANT} { +({DECIMAL_CONSTANT}[uU]?)|({OCTAL_CONSTANT}[uU]?)|({HEXADECIMAL_CONSTANT}[uU]?) { yylval->assign(yytext, yyleng); return pp::Token::CONST_INT; } -({DIGIT}+{EXPONENT_PART})|({FRACTIONAL_CONSTANT}{EXPONENT_PART}?) { +({DIGIT}+{EXPONENT_PART}[fF]?)|({FRACTIONAL_CONSTANT}{EXPONENT_PART}?[fF]?) { yylval->assign(yytext, yyleng); return pp::Token::CONST_FLOAT; } @@ -267,9 +267,7 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".") namespace pp { -Tokenizer::Tokenizer(Diagnostics* diagnostics) - : mHandle(0), - mMaxTokenLength(256) +Tokenizer::Tokenizer(Diagnostics *diagnostics) : mHandle(0) { mContext.diagnostics = diagnostics; } @@ -279,9 +277,10 @@ Tokenizer::~Tokenizer() destroyScanner(); } -bool Tokenizer::init(size_t count, const char* const string[], const int length[]) +bool Tokenizer::init(size_t count, const char * const string[], const int length[]) { - if ((count > 0) && (string == 0)) return false; + if ((count > 0) && (string == 0)) + return false; mContext.input = Input(count, string, length); return initScanner(); @@ -299,14 +298,19 @@ void Tokenizer::setLineNumber(int line) yyset_lineno(line, mHandle); } -void Tokenizer::lex(Token* token) +void Tokenizer::setMaxTokenSize(size_t maxTokenSize) +{ + mMaxTokenSize = maxTokenSize; +} + +void Tokenizer::lex(Token *token) { token->type = yylex(&token->text, &token->location, mHandle); - if (token->text.size() > mMaxTokenLength) + if (token->text.size() > mMaxTokenSize) { mContext.diagnostics->report(Diagnostics::PP_TOKEN_TOO_LONG, token->location, token->text); - token->text.erase(mMaxTokenLength); + token->text.erase(mMaxTokenSize); } token->flags = 0; diff --git a/src/3rdparty/angle/src/compiler/preprocessor/length_limits.h b/src/3rdparty/angle/src/compiler/preprocessor/length_limits.h deleted file mode 100644 index 4f1f71319f..0000000000 --- a/src/3rdparty/angle/src/compiler/preprocessor/length_limits.h +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// length_limits.h -// - -#if !defined(__LENGTH_LIMITS_H) -#define __LENGTH_LIMITS_H 1 - -// These constants are factored out from the rest of the headers to -// make it easier to reference them from the compiler sources. - -// These lengths do not include the NULL terminator. -#define MAX_SYMBOL_NAME_LEN 256 -#define MAX_STRING_LEN 511 - -#endif // !(defined(__LENGTH_LIMITS_H) diff --git a/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h b/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h index b04125d230..8a24540696 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h @@ -13,7 +13,7 @@ namespace pp { -inline std::ios::fmtflags numeric_base_int(const std::string& str) +inline std::ios::fmtflags numeric_base_int(const std::string &str) { if ((str.size() >= 2) && (str[0] == '0') && @@ -21,7 +21,7 @@ inline std::ios::fmtflags numeric_base_int(const std::string& str) { return std::ios::hex; } - else if ((str.size() >= 1) && (str[0] == '0')) + if ((str.size() >= 1) && (str[0] == '0')) { return std::ios::oct; } @@ -34,7 +34,7 @@ inline std::ios::fmtflags numeric_base_int(const std::string& str) // in which case false is returned. template -bool numeric_lex_int(const std::string& str, IntType* value) +bool numeric_lex_int(const std::string &str, IntType *value) { std::istringstream stream(str); // This should not be necessary, but MSVS has a buggy implementation. @@ -46,7 +46,7 @@ bool numeric_lex_int(const std::string& str, IntType* value) } template -bool numeric_lex_float(const std::string& str, FloatType* value) +bool numeric_lex_float(const std::string &str, FloatType *value) { std::istringstream stream(str); // Force "C" locale so that decimal character is always '.', and diff --git a/src/3rdparty/angle/src/compiler/preprocessor/pp_utils.h b/src/3rdparty/angle/src/compiler/preprocessor/pp_utils.h index 17164ea8b0..9fba9385c5 100644 --- a/src/3rdparty/angle/src/compiler/preprocessor/pp_utils.h +++ b/src/3rdparty/angle/src/compiler/preprocessor/pp_utils.h @@ -12,7 +12,7 @@ // A macro to disallow the copy constructor and operator= functions // This must be used in the private: declarations for a class. #define PP_DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) + TypeName(const TypeName &); \ + void operator=(const TypeName &) #endif // COMPILER_PREPROCESSOR_PPUTILS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h index 7bdaf14983..ba9ef5e609 100644 --- a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h +++ b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -7,6 +7,8 @@ #ifndef _BASICTYPES_INCLUDED_ #define _BASICTYPES_INCLUDED_ +#include + // // Precision qualifiers // @@ -38,14 +40,34 @@ enum TBasicType EbtVoid, EbtFloat, EbtInt, + EbtUInt, EbtBool, - EbtGuardSamplerBegin, // non type: see implementation of IsSampler() + EbtGVec4, // non type: represents vec4, ivec4 and uvec4 + EbtGuardSamplerBegin, // non type: see implementation of IsSampler() EbtSampler2D, + EbtSampler3D, EbtSamplerCube, + EbtSampler2DArray, EbtSamplerExternalOES, // Only valid if OES_EGL_image_external exists. EbtSampler2DRect, // Only valid if GL_ARB_texture_rectangle exists. - EbtGuardSamplerEnd, // non type: see implementation of IsSampler() + EbtISampler2D, + EbtISampler3D, + EbtISamplerCube, + EbtISampler2DArray, + EbtUSampler2D, + EbtUSampler3D, + EbtUSamplerCube, + EbtUSampler2DArray, + EbtSampler2DShadow, + EbtSamplerCubeShadow, + EbtSampler2DArrayShadow, + EbtGuardSamplerEnd, // non type: see implementation of IsSampler() + EbtGSampler2D, // non type: represents sampler2D, isampler2D and usampler2D + EbtGSampler3D, // non type: represents sampler3D, isampler3D and usampler3D + EbtGSamplerCube, // non type: represents samplerCube, isamplerCube and usamplerCube + EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray and usampler2DArray EbtStruct, + EbtInterfaceBlock, EbtAddress, // should be deprecated?? EbtInvariant // used as a type when qualifying a previously declared variable as being invariant }; @@ -54,16 +76,31 @@ inline const char* getBasicString(TBasicType t) { switch (t) { - case EbtVoid: return "void"; break; - case EbtFloat: return "float"; break; - case EbtInt: return "int"; break; - case EbtBool: return "bool"; break; - case EbtSampler2D: return "sampler2D"; break; - case EbtSamplerCube: return "samplerCube"; break; - case EbtSamplerExternalOES: return "samplerExternalOES"; break; - case EbtSampler2DRect: return "sampler2DRect"; break; - case EbtStruct: return "structure"; break; - default: return "unknown type"; + 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"; } } @@ -72,6 +109,191 @@ inline bool IsSampler(TBasicType type) return type > EbtGuardSamplerBegin && type < EbtGuardSamplerEnd; } +inline bool IsIntegerSampler(TBasicType type) +{ + switch (type) + { + case EbtISampler2D: + case EbtISampler3D: + case EbtISamplerCube: + case EbtISampler2DArray: + case EbtUSampler2D: + case EbtUSampler3D: + case EbtUSamplerCube: + case EbtUSampler2DArray: + return true; + case EbtSampler2D: + case EbtSampler3D: + case EbtSamplerCube: + case EbtSamplerExternalOES: + case EbtSampler2DRect: + case EbtSampler2DArray: + case EbtSampler2DShadow: + case EbtSamplerCubeShadow: + case EbtSampler2DArrayShadow: + return false; + default: + assert(!IsSampler(type)); + } + + return false; +} + +inline bool IsSampler2D(TBasicType type) +{ + switch (type) + { + case EbtSampler2D: + case EbtISampler2D: + case EbtUSampler2D: + case EbtSampler2DArray: + case EbtISampler2DArray: + case EbtUSampler2DArray: + case EbtSampler2DRect: + case EbtSamplerExternalOES: + case EbtSampler2DShadow: + case EbtSampler2DArrayShadow: + return true; + case EbtSampler3D: + case EbtISampler3D: + case EbtUSampler3D: + case EbtISamplerCube: + case EbtUSamplerCube: + case EbtSamplerCube: + case EbtSamplerCubeShadow: + return false; + default: + assert(!IsSampler(type)); + } + + return false; +} + +inline bool IsSamplerCube(TBasicType type) +{ + switch (type) + { + case EbtSamplerCube: + case EbtISamplerCube: + case EbtUSamplerCube: + case EbtSamplerCubeShadow: + return true; + case EbtSampler2D: + case EbtSampler3D: + case EbtSamplerExternalOES: + case EbtSampler2DRect: + case EbtSampler2DArray: + case EbtISampler2D: + case EbtISampler3D: + case EbtISampler2DArray: + case EbtUSampler2D: + case EbtUSampler3D: + case EbtUSampler2DArray: + case EbtSampler2DShadow: + case EbtSampler2DArrayShadow: + return false; + default: + assert(!IsSampler(type)); + } + + return false; +} + +inline bool IsSampler3D(TBasicType type) +{ + switch (type) + { + case EbtSampler3D: + case EbtISampler3D: + case EbtUSampler3D: + return true; + case EbtSampler2D: + case EbtSamplerCube: + case EbtSamplerExternalOES: + case EbtSampler2DRect: + case EbtSampler2DArray: + case EbtISampler2D: + case EbtISamplerCube: + case EbtISampler2DArray: + case EbtUSampler2D: + case EbtUSamplerCube: + case EbtUSampler2DArray: + case EbtSampler2DShadow: + case EbtSamplerCubeShadow: + case EbtSampler2DArrayShadow: + return false; + default: + assert(!IsSampler(type)); + } + + return false; +} + +inline bool IsSamplerArray(TBasicType type) +{ + switch (type) + { + case EbtSampler2DArray: + case EbtISampler2DArray: + case EbtUSampler2DArray: + case EbtSampler2DArrayShadow: + return true; + case EbtSampler2D: + case EbtISampler2D: + case EbtUSampler2D: + case EbtSampler2DRect: + case EbtSamplerExternalOES: + case EbtSampler3D: + case EbtISampler3D: + case EbtUSampler3D: + case EbtISamplerCube: + case EbtUSamplerCube: + case EbtSamplerCube: + case EbtSampler2DShadow: + case EbtSamplerCubeShadow: + return false; + default: + assert(!IsSampler(type)); + } + + return false; +} + +inline bool IsShadowSampler(TBasicType type) +{ + switch (type) + { + case EbtSampler2DShadow: + case EbtSamplerCubeShadow: + case EbtSampler2DArrayShadow: + return true; + case EbtISampler2D: + case EbtISampler3D: + case EbtISamplerCube: + case EbtISampler2DArray: + case EbtUSampler2D: + case EbtUSampler3D: + case EbtUSamplerCube: + case EbtUSampler2DArray: + case EbtSampler2D: + case EbtSampler3D: + case EbtSamplerCube: + case EbtSamplerExternalOES: + case EbtSampler2DRect: + case EbtSampler2DArray: + return false; + default: + assert(!IsSampler(type)); + } + + return false; +} + +inline bool SupportsPrecision(TBasicType type) +{ + return type == EbtFloat || type == EbtInt || type == EbtUInt || IsSampler(type); +} + // // Qualifiers and built-ins. These are mainly used to see what can be read // or written, and by the machine dependent translator to know which registers @@ -91,6 +313,11 @@ enum TQualifier EvqInvariantVaryingOut, // vertex shaders only read/write EvqUniform, // Readonly, vertex and fragment + EvqVertexIn, // Vertex shader input + EvqFragmentOut, // Fragment shader output + EvqVertexOut, // Vertex shader output + EvqFragmentIn, // Fragment shader input + // parameters EvqIn, EvqOut, @@ -111,10 +338,58 @@ enum TQualifier EvqFragData, EvqFragDepth, + // GLSL ES 3.0 vertex output and fragment input + EvqSmooth, // Incomplete qualifier, smooth is the default + EvqFlat, // Incomplete qualifier + EvqSmoothOut = EvqSmooth, + EvqFlatOut = EvqFlat, + EvqCentroidOut, // Implies smooth + EvqSmoothIn, + EvqFlatIn, + EvqCentroidIn, // Implies smooth + // end of list EvqLast }; +enum TLayoutMatrixPacking +{ + EmpUnspecified, + EmpRowMajor, + EmpColumnMajor +}; + +enum TLayoutBlockStorage +{ + EbsUnspecified, + EbsShared, + EbsPacked, + EbsStd140 +}; + +struct TLayoutQualifier +{ + int location; + TLayoutMatrixPacking matrixPacking; + TLayoutBlockStorage blockStorage; + + static TLayoutQualifier create() + { + TLayoutQualifier layoutQualifier; + + layoutQualifier.location = -1; + layoutQualifier.matrixPacking = EmpUnspecified; + layoutQualifier.blockStorage = EbsUnspecified; + + return layoutQualifier; + } + + bool isEmpty() const + { + return location == -1 && matrixPacking == EmpUnspecified && blockStorage == EbsUnspecified; + } +}; + // // This is just for debug print out, carried along with the definitions above. // @@ -132,6 +407,10 @@ inline const char* getQualifierString(TQualifier q) case EvqInvariantVaryingIn: return "invariant varying"; break; case EvqInvariantVaryingOut:return "invariant varying"; break; case EvqUniform: return "uniform"; break; + case EvqVertexIn: return "in"; break; + case EvqFragmentOut: return "out"; break; + case EvqVertexOut: return "out"; break; + case EvqFragmentIn: return "in"; break; case EvqIn: return "in"; break; case EvqOut: return "out"; break; case EvqInOut: return "inout"; break; @@ -140,10 +419,53 @@ inline const char* getQualifierString(TQualifier q) case EvqFragCoord: return "FragCoord"; break; case EvqFrontFacing: return "FrontFacing"; break; case EvqFragColor: return "FragColor"; break; - case EvqFragData: return "FragData"; break; - case EvqFragDepth: return "FragDepth"; break; + case EvqFragData: return "FragData"; break; + case EvqFragDepth: return "FragDepth"; break; + case EvqSmoothOut: return "smooth out"; break; + case EvqCentroidOut: return "centroid out"; break; + case EvqFlatOut: return "flat out"; break; + case EvqSmoothIn: return "smooth in"; break; + case EvqCentroidIn: return "centroid in"; break; + case EvqFlatIn: return "flat in"; break; default: return "unknown qualifier"; } } +inline const char* getMatrixPackingString(TLayoutMatrixPacking mpq) +{ + switch (mpq) + { + case EmpUnspecified: return "mp_unspecified"; + case EmpRowMajor: return "row_major"; + case EmpColumnMajor: return "column_major"; + default: return "unknown matrix packing"; + } +} + +inline const char* getBlockStorageString(TLayoutBlockStorage bsq) +{ + switch (bsq) + { + case EbsUnspecified: return "bs_unspecified"; + case EbsShared: return "shared"; + case EbsPacked: return "packed"; + case EbsStd140: return "std140"; + default: return "unknown block storage"; + } +} + +inline const char* getInterpolationString(TQualifier q) +{ + switch(q) + { + case EvqSmoothOut: return "smooth"; break; + case EvqCentroidOut: return "centroid"; break; + case EvqFlatOut: return "flat"; break; + case EvqSmoothIn: return "smooth"; break; + case EvqCentroidIn: return "centroid"; break; + case EvqFlatIn: return "flat"; break; + default: return "unknown interpolation"; + } +} + #endif // _BASICTYPES_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp index 92b71c6bdb..0e8239cc1e 100644 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp @@ -4,8 +4,8 @@ // found in the LICENSE file. // +#include "angle_gl.h" #include "compiler/translator/BuiltInFunctionEmulator.h" - #include "compiler/translator/SymbolTable.h" namespace { @@ -243,7 +243,7 @@ public: default: return true; }; - const TIntermSequence& sequence = node->getSequence(); + const TIntermSequence& sequence = *(node->getSequence()); // Right now we only handle built-in functions with two parameters. if (sequence.size() != 2) return true; @@ -265,9 +265,9 @@ private: } // anonymous namepsace -BuiltInFunctionEmulator::BuiltInFunctionEmulator(ShShaderType shaderType) +BuiltInFunctionEmulator::BuiltInFunctionEmulator(sh::GLenum shaderType) { - if (shaderType == SH_FRAGMENT_SHADER) { + if (shaderType == GL_FRAGMENT_SHADER) { mFunctionMask = kFunctionEmulationFragmentMask; mFunctionSource = kFunctionEmulationFragmentSource; } else { @@ -327,7 +327,7 @@ BuiltInFunctionEmulator::TBuiltInFunction BuiltInFunctionEmulator::IdentifyFunction( TOperator op, const TType& param) { - if (param.getNominalSize() > 4) + if (param.getNominalSize() > 4 || param.getSecondarySize() > 4) return TFunctionUnknown; unsigned int function = TFunctionUnknown; switch (op) { @@ -356,9 +356,9 @@ BuiltInFunctionEmulator::IdentifyFunction( { // Right now for all the emulated functions with two parameters, the two // parameters have the same type. - if (param1.isVector() != param2.isVector() || - param1.getNominalSize() != param2.getNominalSize() || - param1.getNominalSize() > 4) + if (param1.getNominalSize() != param2.getNominalSize() || + param1.getSecondarySize() != param2.getSecondarySize() || + param1.getNominalSize() > 4 || param1.getSecondarySize() > 4) return TFunctionUnknown; unsigned int function = TFunctionUnknown; diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h index cfb71a803a..926b6bed69 100644 --- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h +++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h @@ -7,8 +7,6 @@ #ifndef COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ #define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_ -#include "GLSLANG/ShaderLang.h" - #include "compiler/translator/InfoSink.h" #include "compiler/translator/intermediate.h" @@ -19,7 +17,7 @@ // class BuiltInFunctionEmulator { public: - BuiltInFunctionEmulator(ShShaderType shaderType); + BuiltInFunctionEmulator(sh::GLenum shaderType); // Records that a function is called by the shader and might needs to be // emulated. If the function's group is not in mFunctionGroupFilter, this // becomes an no-op. diff --git a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp b/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp index 8f5d129104..71056f4297 100644 --- a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp +++ b/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// 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. // @@ -14,17 +14,17 @@ // a subclass of TCompiler. // TCompiler* ConstructCompiler( - ShShaderType type, ShShaderSpec spec, ShShaderOutput output) + sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) { switch (output) { - case SH_ESSL_OUTPUT: + case SH_ESSL_OUTPUT: return new TranslatorESSL(type, spec); - case SH_GLSL_OUTPUT: + case SH_GLSL_OUTPUT: return new TranslatorGLSL(type, spec); - case SH_HLSL9_OUTPUT: - case SH_HLSL11_OUTPUT: + case SH_HLSL9_OUTPUT: + case SH_HLSL11_OUTPUT: return new TranslatorHLSL(type, spec, output); - default: + default: return NULL; } } diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp index eb7465e35c..0606c72e39 100644 --- a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp @@ -1,33 +1,50 @@ // -// Copyright (c) 2002-2013 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. // #include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/Compiler.h" #include "compiler/translator/DetectCallDepth.h" #include "compiler/translator/ForLoopUnroll.h" #include "compiler/translator/Initialize.h" #include "compiler/translator/InitializeParseContext.h" #include "compiler/translator/InitializeVariables.h" -#include "compiler/translator/MapLongVariableNames.h" #include "compiler/translator/ParseContext.h" #include "compiler/translator/RenameFunction.h" -#include "compiler/translator/ShHandle.h" +#include "compiler/translator/ScalarizeVecAndMatConstructorArgs.h" #include "compiler/translator/UnfoldShortCircuitAST.h" #include "compiler/translator/ValidateLimitations.h" +#include "compiler/translator/ValidateOutputs.h" #include "compiler/translator/VariablePacker.h" #include "compiler/translator/depgraph/DependencyGraph.h" #include "compiler/translator/depgraph/DependencyGraphOutput.h" #include "compiler/translator/timing/RestrictFragmentShaderTiming.h" #include "compiler/translator/timing/RestrictVertexShaderTiming.h" #include "third_party/compiler/ArrayBoundsClamper.h" +#include "angle_gl.h" +#include "common/utilities.h" -bool isWebGLBasedSpec(ShShaderSpec spec) +bool IsWebGLBasedSpec(ShShaderSpec spec) { return spec == SH_WEBGL_SPEC || spec == SH_CSS_SHADERS_SPEC; } +size_t GetGlobalMaxTokenSize(ShShaderSpec spec) +{ + // WebGL defines a max token legnth of 256, while ES2 leaves max token + // size undefined. ES3 defines a max size of 1024 characters. + if (IsWebGLBasedSpec(spec)) + { + return 256; + } + else + { + return 1024; + } +} + namespace { class TScopedPoolAllocator { @@ -78,9 +95,10 @@ TShHandleBase::~TShHandleBase() allocator.popAll(); } -TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec) +TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) : shaderType(type), shaderSpec(spec), + outputType(output), maxUniformVectors(0), maxExpressionComplexity(0), maxCallStackDepth(0), @@ -88,18 +106,16 @@ TCompiler::TCompiler(ShShaderType type, ShShaderSpec spec) clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC), builtInFunctionEmulator(type) { - longNameMap = LongNameMap::GetInstance(); } TCompiler::~TCompiler() { - ASSERT(longNameMap); - longNameMap->Release(); } bool TCompiler::Init(const ShBuiltInResources& resources) { - maxUniformVectors = (shaderType == SH_VERTEX_SHADER) ? + shaderVersion = 100; + maxUniformVectors = (shaderType == GL_VERTEX_SHADER) ? resources.MaxVertexUniformVectors : resources.MaxFragmentUniformVectors; maxExpressionComplexity = resources.MaxExpressionComplexity; @@ -132,7 +148,7 @@ bool TCompiler::compile(const char* const shaderStrings[], return true; // If compiling for WebGL, validate loop and indexing as well. - if (isWebGLBasedSpec(shaderSpec)) + if (IsWebGLBasedSpec(shaderSpec)) compileOptions |= SH_VALIDATE_LOOP_INDEXING; // First string is path of source file if flag is set. The actual source follows. @@ -159,14 +175,24 @@ bool TCompiler::compile(const char* const shaderStrings[], bool success = (PaParseStrings(numStrings - firstSource, &shaderStrings[firstSource], NULL, &parseContext) == 0) && (parseContext.treeRoot != NULL); + + shaderVersion = parseContext.getShaderVersion(); + if (success) { TIntermNode* root = parseContext.treeRoot; success = intermediate.postProcess(root); + // Disallow expressions deemed too complex. + if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY)) + success = limitExpressionComplexity(root); + if (success) success = detectCallDepth(root, infoSink, (compileOptions & SH_LIMIT_CALL_STACK_DEPTH) != 0); + if (success && shaderVersion == 300 && shaderType == GL_FRAGMENT_SHADER) + success = validateOutputs(root); + if (success && (compileOptions & SH_VALIDATE_LOOP_INDEXING)) success = validateLimitations(root); @@ -178,7 +204,21 @@ bool TCompiler::compile(const char* const shaderStrings[], // Unroll for-loop markup needs to happen after validateLimitations pass. if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_INTEGER_INDEX)) - ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling(root); + { + ForLoopUnrollMarker marker(ForLoopUnrollMarker::kIntegerIndex); + root->traverse(&marker); + } + if (success && (compileOptions & SH_UNROLL_FOR_LOOP_WITH_SAMPLER_ARRAY_INDEX)) + { + ForLoopUnrollMarker marker(ForLoopUnrollMarker::kSamplerArrayIndex); + root->traverse(&marker); + if (marker.samplerArrayIndexIsFloatLoopIndex()) + { + infoSink.info.prefix(EPrefixError); + infoSink.info << "sampler array index is float loop index"; + success = false; + } + } // Built-in function emulation needs to happen after validateLimitations pass. if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS)) @@ -188,18 +228,7 @@ bool TCompiler::compile(const char* const shaderStrings[], if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS)) arrayBoundsClamper.MarkIndirectArrayBoundsForClamping(root); - // Disallow expressions deemed too complex. - if (success && (compileOptions & SH_LIMIT_EXPRESSION_COMPLEXITY)) - success = limitExpressionComplexity(root); - - // Call mapLongVariableNames() before collectAttribsUniforms() so in - // collectAttribsUniforms() we already have the mapped symbol names and - // we could composite mapped and original variable names. - // Also, if we hash all the names, then no need to do this for long names. - if (success && (compileOptions & SH_MAP_LONG_VARIABLE_NAMES) && hashFunction == NULL) - mapLongVariableNames(root); - - if (success && shaderType == SH_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION)) + if (success && shaderType == GL_VERTEX_SHADER && (compileOptions & SH_INIT_GL_POSITION)) initializeGLPosition(root); if (success && (compileOptions & SH_UNFOLD_SHORT_CIRCUIT)) @@ -221,11 +250,17 @@ bool TCompiler::compile(const char* const shaderStrings[], infoSink.info << "too many uniforms"; } } - if (success && shaderType == SH_VERTEX_SHADER && + if (success && shaderType == GL_VERTEX_SHADER && (compileOptions & SH_INIT_VARYINGS_WITHOUT_STATIC_USE)) initializeVaryingsWithoutStaticUse(root); } + if (success && (compileOptions & SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS)) + { + ScalarizeVecAndMatConstructorArgs scalarizer; + root->traverse(&scalarizer); + } + if (success && (compileOptions & SH_INTERMEDIATE_TREE)) intermediate.outputTree(root); @@ -235,40 +270,43 @@ bool TCompiler::compile(const char* const shaderStrings[], // Cleanup memory. intermediate.remove(parseContext.treeRoot); - + SetGlobalParseContext(NULL); return success; } bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources) { compileResources = resources; + setResourceString(); assert(symbolTable.isEmpty()); - symbolTable.push(); + symbolTable.push(); // COMMON_BUILTINS + symbolTable.push(); // ESSL1_BUILTINS + symbolTable.push(); // ESSL3_BUILTINS TPublicType integer; integer.type = EbtInt; - integer.size = 1; - integer.matrix = false; + integer.primarySize = 1; + integer.secondarySize = 1; integer.array = false; TPublicType floatingPoint; floatingPoint.type = EbtFloat; - floatingPoint.size = 1; - floatingPoint.matrix = false; + floatingPoint.primarySize = 1; + floatingPoint.secondarySize = 1; floatingPoint.array = false; TPublicType sampler; - sampler.size = 1; - sampler.matrix = false; + sampler.primarySize = 1; + sampler.secondarySize = 1; sampler.array = false; switch(shaderType) { - case SH_FRAGMENT_SHADER: + case GL_FRAGMENT_SHADER: symbolTable.setDefaultPrecision(integer, EbpMedium); break; - case SH_VERTEX_SHADER: + case GL_VERTEX_SHADER: symbolTable.setDefaultPrecision(integer, EbpHigh); symbolTable.setDefaultPrecision(floatingPoint, EbpHigh); break; @@ -291,6 +329,34 @@ bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources) return true; } +void TCompiler::setResourceString() +{ + std::ostringstream strstream; + strstream << ":MaxVertexAttribs:" << compileResources.MaxVertexAttribs + << ":MaxVertexUniformVectors:" << compileResources.MaxVertexUniformVectors + << ":MaxVaryingVectors:" << compileResources.MaxVaryingVectors + << ":MaxVertexTextureImageUnits:" << compileResources.MaxVertexTextureImageUnits + << ":MaxCombinedTextureImageUnits:" << compileResources.MaxCombinedTextureImageUnits + << ":MaxTextureImageUnits:" << compileResources.MaxTextureImageUnits + << ":MaxFragmentUniformVectors:" << compileResources.MaxFragmentUniformVectors + << ":MaxDrawBuffers:" << compileResources.MaxDrawBuffers + << ":OES_standard_derivatives:" << compileResources.OES_standard_derivatives + << ":OES_EGL_image_external:" << compileResources.OES_EGL_image_external + << ":ARB_texture_rectangle:" << compileResources.ARB_texture_rectangle + << ":EXT_draw_buffers:" << compileResources.EXT_draw_buffers + << ":FragmentPrecisionHigh:" << compileResources.FragmentPrecisionHigh + << ":MaxExpressionComplexity:" << compileResources.MaxExpressionComplexity + << ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth + << ":EXT_frag_depth:" << compileResources.EXT_frag_depth + << ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod + << ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors + << ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors + << ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset + << ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset; + + builtInResourcesString = strstream.str(); +} + void TCompiler::clearResults() { arrayBoundsClamper.Cleanup(); @@ -298,9 +364,13 @@ void TCompiler::clearResults() infoSink.obj.erase(); infoSink.debug.erase(); - attribs.clear(); + attributes.clear(); + outputVariables.clear(); uniforms.clear(); + expandedUniforms.clear(); varyings.clear(); + expandedVaryings.clear(); + interfaceBlocks.clear(); builtInFunctionEmulator.Cleanup(); @@ -333,6 +403,13 @@ bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool lim } } +bool TCompiler::validateOutputs(TIntermNode* root) +{ + ValidateOutputs validateOutputs(infoSink.info, compileResources.MaxDrawBuffers); + root->traverse(&validateOutputs); + return (validateOutputs.numErrors() == 0); +} + void TCompiler::rewriteCSSShader(TIntermNode* root) { RenameFunction renamer("main(", "css_main("); @@ -354,20 +431,20 @@ bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph) return false; } - if (shaderType == SH_FRAGMENT_SHADER) + if (shaderType == GL_FRAGMENT_SHADER) { TDependencyGraph graph(root); // Output any errors first. bool success = enforceFragmentShaderTimingRestrictions(graph); - + // Then, output the dependency graph. if (outputGraph) { TDependencyGraphOutput output(infoSink.info); output.outputAllSpanningTrees(graph); } - + return success; } else @@ -378,8 +455,15 @@ bool TCompiler::enforceTimingRestrictions(TIntermNode* root, bool outputGraph) bool TCompiler::limitExpressionComplexity(TIntermNode* root) { - TIntermTraverser traverser; + TMaxDepthTraverser traverser(maxExpressionComplexity+1); root->traverse(&traverser); + + if (traverser.getMaxDepth() > maxExpressionComplexity) + { + infoSink.info << "Expression too complex."; + return false; + } + TDependencyGraph graph(root); for (TFunctionCallVector::const_iterator iter = graph.beginUserDefinedFunctionCalls(); @@ -391,11 +475,6 @@ bool TCompiler::limitExpressionComplexity(TIntermNode* root) samplerSymbol->traverse(&graphTraverser); } - if (traverser.getMaxDepth() > maxExpressionComplexity) - { - infoSink.info << "Expression too complex."; - return false; - } return true; } @@ -415,14 +494,24 @@ bool TCompiler::enforceVertexShaderTimingRestrictions(TIntermNode* root) void TCompiler::collectVariables(TIntermNode* root) { - CollectVariables collect(attribs, uniforms, varyings, hashFunction); + 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); } bool TCompiler::enforcePackingRestrictions() { VariablePacker packer; - return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, uniforms); + return packer.CheckVariablesWithinPackingLimits(maxUniformVectors, expandedUniforms); } void TCompiler::initializeGLPosition(TIntermNode* root) @@ -440,45 +529,16 @@ void TCompiler::initializeVaryingsWithoutStaticUse(TIntermNode* root) InitializeVariables::InitVariableInfoList variables; for (size_t ii = 0; ii < varyings.size(); ++ii) { - const TVariableInfo& varying = varyings[ii]; + const sh::Varying& varying = varyings[ii]; if (varying.staticUse) continue; - unsigned char size = 0; - bool matrix = false; - switch (varying.type) - { - case SH_FLOAT: - size = 1; - break; - case SH_FLOAT_VEC2: - size = 2; - break; - case SH_FLOAT_VEC3: - size = 3; - break; - case SH_FLOAT_VEC4: - size = 4; - break; - case SH_FLOAT_MAT2: - size = 2; - matrix = true; - break; - case SH_FLOAT_MAT3: - size = 3; - matrix = true; - break; - case SH_FLOAT_MAT4: - size = 4; - matrix = true; - break; - default: - ASSERT(false); - } - TType type(EbtFloat, EbpUndefined, EvqVaryingOut, size, matrix, varying.isArray); + unsigned char primarySize = static_cast(gl::VariableColumnCount(varying.type)); + unsigned char secondarySize = static_cast(gl::VariableRowCount(varying.type)); + TType type(EbtFloat, EbpUndefined, EvqVaryingOut, primarySize, secondarySize, varying.isArray()); TString name = varying.name.c_str(); - if (varying.isArray) + if (varying.isArray()) { - type.setArraySize(varying.size); + type.setArraySize(varying.arraySize); name = name.substr(0, name.find_first_of('[')); } @@ -489,18 +549,6 @@ void TCompiler::initializeVaryingsWithoutStaticUse(TIntermNode* root) root->traverse(&initializer); } -void TCompiler::mapLongVariableNames(TIntermNode* root) -{ - ASSERT(longNameMap); - MapLongVariableNames map(longNameMap); - root->traverse(&map); -} - -int TCompiler::getMappedNameMaxLength() const -{ - return MAX_SHORTENED_IDENTIFIER_SIZE + 1; -} - const TExtensionBehavior& TCompiler::getExtensionBehavior() const { return extensionBehavior; diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.h b/src/3rdparty/angle/src/compiler/translator/Compiler.h new file mode 100644 index 0000000000..5eac2d89d1 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Compiler.h @@ -0,0 +1,191 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef _SHHANDLE_INCLUDED_ +#define _SHHANDLE_INCLUDED_ + +// +// Machine independent part of the compiler private objects +// sent as ShHandle to the driver. +// +// This should not be included by driver code. +// + +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "compiler/translator/ExtensionBehavior.h" +#include "compiler/translator/HashNames.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/SymbolTable.h" +#include "compiler/translator/VariableInfo.h" +#include "third_party/compiler/ArrayBoundsClamper.h" + +class TCompiler; +class TDependencyGraph; +class TranslatorHLSL; + +// +// Helper function to identify specs that are based on the WebGL spec, +// like the CSS Shaders spec. +// +bool IsWebGLBasedSpec(ShShaderSpec spec); + +// +// The base class used to back handles returned to the driver. +// +class TShHandleBase { +public: + TShHandleBase(); + virtual ~TShHandleBase(); + virtual TCompiler* getAsCompiler() { return 0; } + virtual TranslatorHLSL* getAsTranslatorHLSL() { return 0; } + +protected: + // Memory allocator. Allocates and tracks memory required by the compiler. + // Deallocates all memory when compiler is destructed. + TPoolAllocator allocator; +}; + +// +// The base class for the machine dependent compiler to derive from +// for managing object code from the compile. +// +class TCompiler : public TShHandleBase +{ + public: + TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); + virtual ~TCompiler(); + virtual TCompiler* getAsCompiler() { return this; } + + bool Init(const ShBuiltInResources& resources); + bool compile(const char* const shaderStrings[], + size_t numStrings, + int compileOptions); + + // Get results of the last compilation. + int getShaderVersion() const { return shaderVersion; } + TInfoSink& getInfoSink() { return infoSink; } + + 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 &getVaryings() const { return varyings; } + const std::vector &getExpandedVaryings() const { return expandedVaryings; } + const std::vector &getInterfaceBlocks() const { return interfaceBlocks; } + + ShHashFunction64 getHashFunction() const { return hashFunction; } + NameMap& getNameMap() { return nameMap; } + TSymbolTable& getSymbolTable() { return symbolTable; } + ShShaderSpec getShaderSpec() const { return shaderSpec; } + ShShaderOutput getOutputType() const { return outputType; } + std::string getBuiltInResourcesString() const { return builtInResourcesString; } + + protected: + sh::GLenum getShaderType() const { return shaderType; } + // Initialize symbol-table with built-in symbols. + bool InitBuiltInSymbolTable(const ShBuiltInResources& resources); + // Compute the string representation of the built-in resources + void setResourceString(); + // Clears the results from the previous compilation. + void clearResults(); + // Return true if function recursion is detected or call depth exceeded. + bool detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth); + // Returns true if a program has no conflicting or missing fragment outputs + bool validateOutputs(TIntermNode* root); + // Rewrites a shader's intermediate tree according to the CSS Shaders spec. + void rewriteCSSShader(TIntermNode* root); + // Returns true if the given shader does not exceed the minimum + // functionality mandated in GLSL 1.0 spec Appendix A. + bool validateLimitations(TIntermNode* root); + // Collect info for all attribs, uniforms, varyings. + void collectVariables(TIntermNode* root); + // Translate to object code. + virtual void translate(TIntermNode* root) = 0; + // Returns true if, after applying the packing rules in the GLSL 1.017 spec + // Appendix A, section 7, the shader does not use too many uniforms. + bool enforcePackingRestrictions(); + // Insert statements to initialize varyings without static use in the beginning + // of main(). It is to work around a Mac driver where such varyings in a vertex + // shader may be optimized out incorrectly at compile time, causing a link failure. + // This function should only be applied to vertex shaders. + void initializeVaryingsWithoutStaticUse(TIntermNode* root); + // Insert gl_Position = vec4(0,0,0,0) to the beginning of main(). + // It is to work around a Linux driver bug where missing this causes compile failure + // while spec says it is allowed. + // This function should only be applied to vertex shaders. + void initializeGLPosition(TIntermNode* root); + // Returns true if the shader passes the restrictions that aim to prevent timing attacks. + bool enforceTimingRestrictions(TIntermNode* root, bool outputGraph); + // Returns true if the shader does not use samplers. + bool enforceVertexShaderTimingRestrictions(TIntermNode* root); + // Returns true if the shader does not use sampler dependent values to affect control + // flow or in operations whose time can depend on the input values. + bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph); + // Return true if the maximum expression complexity is below the limit. + bool limitExpressionComplexity(TIntermNode* root); + // Get built-in extensions with default behavior. + const TExtensionBehavior& getExtensionBehavior() const; + // Get the resources set by InitBuiltInSymbolTable + const ShBuiltInResources& getResources() const; + + const ArrayBoundsClamper& getArrayBoundsClamper() const; + ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const; + const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const; + + std::vector attributes; + std::vector outputVariables; + std::vector uniforms; + std::vector expandedUniforms; + std::vector varyings; + std::vector expandedVaryings; + std::vector interfaceBlocks; + + private: + sh::GLenum shaderType; + ShShaderSpec shaderSpec; + ShShaderOutput outputType; + + int maxUniformVectors; + int maxExpressionComplexity; + int maxCallStackDepth; + + ShBuiltInResources compileResources; + std::string builtInResourcesString; + + // Built-in symbol table for the given language, spec, and resources. + // It is preserved from compile-to-compile. + TSymbolTable symbolTable; + // Built-in extensions with default behavior. + TExtensionBehavior extensionBehavior; + bool fragmentPrecisionHigh; + + ArrayBoundsClamper arrayBoundsClamper; + ShArrayIndexClampingStrategy clampingStrategy; + BuiltInFunctionEmulator builtInFunctionEmulator; + + // Results of compilation. + int shaderVersion; + TInfoSink infoSink; // Output sink. + + // name hashing. + ShHashFunction64 hashFunction; + NameMap nameMap; +}; + +// +// This is the interface between the machine independent code +// and the machine dependent code. +// +// The machine dependent code should derive from the classes +// above. Then Construct*() and Delete*() will create and +// destroy the machine dependent objects, which contain the +// above machine independent information. +// +TCompiler* ConstructCompiler( + sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); +void DeleteCompiler(TCompiler*); + +#endif // _SHHANDLE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h index b1e37885f9..5e86c64805 100644 --- a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h +++ b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2013 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. // @@ -18,14 +18,74 @@ public: type = EbtVoid; } + bool cast(TBasicType newType, const ConstantUnion &constant) + { + switch (newType) + { + case EbtFloat: + switch (constant.type) + { + case EbtInt: setFConst(static_cast(constant.getIConst())); break; + case EbtUInt: setFConst(static_cast(constant.getUConst())); break; + case EbtBool: setFConst(static_cast(constant.getBConst())); break; + case EbtFloat: setFConst(static_cast(constant.getFConst())); break; + default: return false; + } + break; + case EbtInt: + switch (constant.type) + { + case EbtInt: setIConst(static_cast(constant.getIConst())); break; + case EbtUInt: setIConst(static_cast(constant.getUConst())); break; + case EbtBool: setIConst(static_cast(constant.getBConst())); break; + case EbtFloat: setIConst(static_cast(constant.getFConst())); break; + default: return false; + } + break; + case EbtUInt: + switch (constant.type) + { + case EbtInt: setUConst(static_cast(constant.getIConst())); break; + case EbtUInt: setUConst(static_cast(constant.getUConst())); break; + case EbtBool: setUConst(static_cast(constant.getBConst())); break; + case EbtFloat: setUConst(static_cast(constant.getFConst())); break; + default: return false; + } + break; + case EbtBool: + switch (constant.type) + { + case EbtInt: setBConst(constant.getIConst() != 0); break; + case EbtUInt: setBConst(constant.getUConst() != 0); break; + case EbtBool: setBConst(constant.getBConst()); break; + case EbtFloat: setBConst(constant.getFConst() != 0.0f); break; + default: return false; + } + break; + case EbtStruct: // Struct fields don't get cast + switch (constant.type) + { + case EbtInt: setIConst(constant.getIConst()); break; + case EbtUInt: setUConst(constant.getUConst()); break; + case EbtBool: setBConst(constant.getBConst()); break; + case EbtFloat: setFConst(constant.getFConst()); break; + default: return false; + } + break; + default: + return false; + } + + return true; + } + void setIConst(int i) {iConst = i; type = EbtInt; } + void setUConst(unsigned int u) { uConst = u; type = EbtUInt; } void setFConst(float f) {fConst = f; type = EbtFloat; } void setBConst(bool b) {bConst = b; type = EbtBool; } - int getIConst() { return iConst; } - float getFConst() { return fConst; } - bool getBConst() { return bConst; } int getIConst() const { return iConst; } + unsigned int getUConst() const { return uConst; } float getFConst() const { return fConst; } bool getBConst() const { return bConst; } @@ -34,6 +94,11 @@ public: return i == iConst; } + bool operator==(const unsigned int u) const + { + return u == uConst; + } + bool operator==(const float f) const { return f == fConst; @@ -52,6 +117,8 @@ public: switch (type) { case EbtInt: return constant.iConst == iConst; + case EbtUInt: + return constant.uConst == uConst; case EbtFloat: return constant.fConst == fConst; case EbtBool: @@ -66,6 +133,11 @@ public: return !operator==(i); } + bool operator!=(const unsigned int u) const + { + return !operator==(u); + } + bool operator!=(const float f) const { return !operator==(f); @@ -87,6 +159,8 @@ public: switch (type) { case EbtInt: return iConst > constant.iConst; + case EbtUInt: + return uConst > constant.uConst; case EbtFloat: return fConst > constant.fConst; default: @@ -100,6 +174,8 @@ public: switch (type) { case EbtInt: return iConst < constant.iConst; + case EbtUInt: + return uConst < constant.uConst; case EbtFloat: return fConst < constant.fConst; default: @@ -113,6 +189,7 @@ public: assert(type == constant.type); switch (type) { case EbtInt: returnValue.setIConst(iConst + constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst + constant.uConst); break; case EbtFloat: returnValue.setFConst(fConst + constant.fConst); break; default: assert(false && "Default missing"); } @@ -126,6 +203,7 @@ public: assert(type == constant.type); switch (type) { case EbtInt: returnValue.setIConst(iConst - constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst - constant.uConst); break; case EbtFloat: returnValue.setFConst(fConst - constant.fConst); break; default: assert(false && "Default missing"); } @@ -139,6 +217,7 @@ public: assert(type == constant.type); switch (type) { case EbtInt: returnValue.setIConst(iConst * constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst * constant.uConst); break; case EbtFloat: returnValue.setFConst(fConst * constant.fConst); break; default: assert(false && "Default missing"); } @@ -152,6 +231,7 @@ public: assert(type == constant.type); switch (type) { case EbtInt: returnValue.setIConst(iConst % constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst % constant.uConst); break; default: assert(false && "Default missing"); } @@ -164,6 +244,7 @@ public: assert(type == constant.type); switch (type) { case EbtInt: returnValue.setIConst(iConst >> constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst >> constant.uConst); break; default: assert(false && "Default missing"); } @@ -176,6 +257,7 @@ public: assert(type == constant.type); switch (type) { case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break; default: assert(false && "Default missing"); } @@ -188,6 +270,7 @@ public: assert(type == constant.type); switch (type) { case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst & constant.uConst); break; default: assert(false && "Default missing"); } @@ -200,6 +283,7 @@ public: assert(type == constant.type); switch (type) { case EbtInt: returnValue.setIConst(iConst | constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst | constant.uConst); break; default: assert(false && "Default missing"); } @@ -212,6 +296,7 @@ public: assert(type == constant.type); switch (type) { case EbtInt: returnValue.setIConst(iConst ^ constant.iConst); break; + case EbtUInt: returnValue.setUConst(uConst ^ constant.uConst); break; default: assert(false && "Default missing"); } @@ -247,6 +332,7 @@ private: union { int iConst; // used for ivec, scalar ints + unsigned int uConst; // used for uvec, scalar uints bool bConst; // used for bvec, scalar bools float fConst; // used for vec, mat, scalar floats } ; diff --git a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h index 5e7f23d15f..cb76f1de02 100644 --- a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h +++ b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h @@ -7,8 +7,6 @@ #ifndef COMPILER_DETECT_RECURSION_H_ #define COMPILER_DETECT_RECURSION_H_ -#include "GLSLANG/ShaderLang.h" - #include #include "compiler/translator/intermediate.h" #include "compiler/translator/VariableInfo.h" diff --git a/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp b/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp index 99506c0849..92db3e55cf 100644 --- a/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Diagnostics.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // diff --git a/src/3rdparty/angle/src/compiler/translator/Diagnostics.h b/src/3rdparty/angle/src/compiler/translator/Diagnostics.h index cb71bb1204..664da7803b 100644 --- a/src/3rdparty/angle/src/compiler/translator/Diagnostics.h +++ b/src/3rdparty/angle/src/compiler/translator/Diagnostics.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp index 662c8ae624..59d2835f7b 100644 --- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp +++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -26,9 +26,11 @@ static TBehavior getBehavior(const std::string& str) } TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior, - TDiagnostics& diagnostics) + TDiagnostics& diagnostics, + int& shaderVersion) : mExtensionBehavior(extBehavior), - mDiagnostics(diagnostics) + mDiagnostics(diagnostics), + mShaderVersion(shaderVersion) { } @@ -148,9 +150,12 @@ void TDirectiveHandler::handleExtension(const pp::SourceLocation& loc, void TDirectiveHandler::handleVersion(const pp::SourceLocation& loc, int version) { - static const int kVersion = 100; - - if (version != kVersion) + if (version == 100 || + version == 300) + { + mShaderVersion = version; + } + else { std::stringstream stream; stream << version; diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h index eb5f055494..69418c277a 100644 --- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h +++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h @@ -17,7 +17,8 @@ class TDirectiveHandler : public pp::DirectiveHandler { public: TDirectiveHandler(TExtensionBehavior& extBehavior, - TDiagnostics& diagnostics); + TDiagnostics& diagnostics, + int& shaderVersion); virtual ~TDirectiveHandler(); const TPragma& pragma() const { return mPragma; } @@ -41,6 +42,7 @@ class TDirectiveHandler : public pp::DirectiveHandler TPragma mPragma; TExtensionBehavior& mExtensionBehavior; TDiagnostics& mDiagnostics; + int& mShaderVersion; }; #endif // COMPILER_DIRECTIVE_HANDLER_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp new file mode 100644 index 0000000000..a751b768b7 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.cpp @@ -0,0 +1,77 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/FlagStd140Structs.h" + +namespace sh +{ + +bool FlagStd140Structs::visitBinary(Visit visit, TIntermBinary *binaryNode) +{ + if (binaryNode->getRight()->getBasicType() == EbtStruct) + { + switch (binaryNode->getOp()) + { + case EOpIndexDirectInterfaceBlock: + case EOpIndexDirectStruct: + if (isInStd140InterfaceBlock(binaryNode->getLeft())) + { + mFlaggedNodes.push_back(binaryNode); + } + break; + + default: break; + } + return false; + } + + if (binaryNode->getOp() == EOpIndexDirectStruct) + { + return false; + } + + return visit == PreVisit; +} + +void FlagStd140Structs::visitSymbol(TIntermSymbol *symbol) +{ + if (isInStd140InterfaceBlock(symbol) && symbol->getBasicType() == EbtStruct) + { + mFlaggedNodes.push_back(symbol); + } +} + +bool FlagStd140Structs::isInStd140InterfaceBlock(TIntermTyped *node) const +{ + TIntermBinary *binaryNode = node->getAsBinaryNode(); + + if (binaryNode) + { + return isInStd140InterfaceBlock(binaryNode->getLeft()); + } + + const TType &type = node->getType(); + + // determine if we are in the standard layout + const TInterfaceBlock *interfaceBlock = type.getInterfaceBlock(); + if (interfaceBlock) + { + return (interfaceBlock->blockStorage() == EbsStd140); + } + + return false; +} + +std::vector FlagStd140ValueStructs(TIntermNode *node) +{ + FlagStd140Structs flaggingTraversal; + + node->traverse(&flaggingTraversal); + + return flaggingTraversal.getFlaggedNodes(); +} + +} diff --git a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h new file mode 100644 index 0000000000..610205eb92 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h @@ -0,0 +1,37 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef COMPILER_FLAGSTD140STRUCTS_H_ +#define COMPILER_FLAGSTD140STRUCTS_H_ + +#include "compiler/translator/intermediate.h" + +namespace sh +{ + +// This class finds references to nested structs of std140 blocks that access +// the nested struct "by value", where the padding added in the translator +// conflicts with the "natural" unpadded type. +class FlagStd140Structs : public TIntermTraverser +{ + public: + const std::vector getFlaggedNodes() const { return mFlaggedNodes; } + + protected: + virtual bool visitBinary(Visit visit, TIntermBinary *binaryNode); + virtual void visitSymbol(TIntermSymbol *symbol); + + private: + bool isInStd140InterfaceBlock(TIntermTyped *node) const; + + std::vector mFlaggedNodes; +}; + +std::vector FlagStd140ValueStructs(TIntermNode *node); + +} + +#endif // COMPILER_FLAGSTD140STRUCTS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.cpp b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.cpp index 89e6f1a62b..f3be20d978 100644 --- a/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.cpp @@ -6,210 +6,77 @@ #include "compiler/translator/ForLoopUnroll.h" -namespace { - -class IntegerForLoopUnrollMarker : public TIntermTraverser { -public: - - virtual bool visitLoop(Visit, TIntermLoop* node) - { - // This is called after ValidateLimitations pass, so all the ASSERT - // should never fail. - // See ValidateLimitations::validateForLoopInit(). - ASSERT(node); - ASSERT(node->getType() == ELoopFor); - ASSERT(node->getInit()); - TIntermAggregate* decl = node->getInit()->getAsAggregate(); - ASSERT(decl && decl->getOp() == EOpDeclaration); - TIntermSequence& declSeq = decl->getSequence(); - ASSERT(declSeq.size() == 1); - TIntermBinary* declInit = declSeq[0]->getAsBinaryNode(); - ASSERT(declInit && declInit->getOp() == EOpInitialize); - ASSERT(declInit->getLeft()); - TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode(); - ASSERT(symbol); - TBasicType type = symbol->getBasicType(); - ASSERT(type == EbtInt || type == EbtFloat); - if (type == EbtInt) - node->setUnrollFlag(true); - return true; - } - -}; - -} // anonymous namepsace - -void ForLoopUnroll::FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info) +bool ForLoopUnrollMarker::visitBinary(Visit, TIntermBinary *node) { - ASSERT(node->getType() == ELoopFor); - ASSERT(node->getUnrollFlag()); - - TIntermNode* init = node->getInit(); - ASSERT(init != NULL); - TIntermAggregate* decl = init->getAsAggregate(); - ASSERT((decl != NULL) && (decl->getOp() == EOpDeclaration)); - TIntermSequence& declSeq = decl->getSequence(); - ASSERT(declSeq.size() == 1); - TIntermBinary* declInit = declSeq[0]->getAsBinaryNode(); - ASSERT((declInit != NULL) && (declInit->getOp() == EOpInitialize)); - TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode(); - ASSERT(symbol != NULL); - ASSERT(symbol->getBasicType() == EbtInt); - - info.id = symbol->getId(); - - ASSERT(declInit->getRight() != NULL); - TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion(); - ASSERT(initNode != NULL); - - info.initValue = evaluateIntConstant(initNode); - info.currentValue = info.initValue; - - TIntermNode* cond = node->getCondition(); - ASSERT(cond != NULL); - TIntermBinary* binOp = cond->getAsBinaryNode(); - ASSERT(binOp != NULL); - ASSERT(binOp->getRight() != NULL); - ASSERT(binOp->getRight()->getAsConstantUnion() != NULL); - - info.incrementValue = getLoopIncrement(node); - info.stopValue = evaluateIntConstant( - binOp->getRight()->getAsConstantUnion()); - info.op = binOp->getOp(); -} - -void ForLoopUnroll::Step() -{ - ASSERT(mLoopIndexStack.size() > 0); - TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1]; - info.currentValue += info.incrementValue; -} + if (mUnrollCondition != kSamplerArrayIndex) + return true; -bool ForLoopUnroll::SatisfiesLoopCondition() -{ - ASSERT(mLoopIndexStack.size() > 0); - TLoopIndexInfo& info = mLoopIndexStack[mLoopIndexStack.size() - 1]; - // Relational operator is one of: > >= < <= == or !=. - switch (info.op) { - case EOpEqual: - return (info.currentValue == info.stopValue); - case EOpNotEqual: - return (info.currentValue != info.stopValue); - case EOpLessThan: - return (info.currentValue < info.stopValue); - case EOpGreaterThan: - return (info.currentValue > info.stopValue); - case EOpLessThanEqual: - return (info.currentValue <= info.stopValue); - case EOpGreaterThanEqual: - return (info.currentValue >= info.stopValue); + // If a sampler array index is also the loop index, + // 1) if the index type is integer, mark the loop for unrolling; + // 2) if the index type if float, set a flag to later fail compile. + switch (node->getOp()) + { + case EOpIndexIndirect: + if (node->getLeft() != NULL && node->getRight() != NULL && node->getLeft()->getAsSymbolNode()) + { + TIntermSymbol *symbol = node->getLeft()->getAsSymbolNode(); + if (IsSampler(symbol->getBasicType()) && symbol->isArray() && !mLoopStack.empty()) + { + mVisitSamplerArrayIndexNodeInsideLoop = true; + node->getRight()->traverse(this); + mVisitSamplerArrayIndexNodeInsideLoop = false; + // We have already visited all the children. + return false; + } + } + break; default: - UNREACHABLE(); + break; } - return false; + return true; } -bool ForLoopUnroll::NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol) +bool ForLoopUnrollMarker::visitLoop(Visit, TIntermLoop *node) { - for (TVector::iterator i = mLoopIndexStack.begin(); - i != mLoopIndexStack.end(); - ++i) { - if (i->id == symbol->getId()) - return true; + if (mUnrollCondition == kIntegerIndex) + { + // Check if loop index type is integer. + // This is called after ValidateLimitations pass, so all the calls + // should be valid. See ValidateLimitations::validateForLoopInit(). + TIntermSequence *declSeq = node->getInit()->getAsAggregate()->getSequence(); + TIntermSymbol *symbol = (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode(); + if (symbol->getBasicType() == EbtInt) + node->setUnrollFlag(true); } - return false; -} -int ForLoopUnroll::GetLoopIndexValue(TIntermSymbol* symbol) -{ - for (TVector::iterator i = mLoopIndexStack.begin(); - i != mLoopIndexStack.end(); - ++i) { - if (i->id == symbol->getId()) - return i->currentValue; + TIntermNode *body = node->getBody(); + if (body != NULL) + { + mLoopStack.push(node); + body->traverse(this); + mLoopStack.pop(); } - UNREACHABLE(); + // The loop is fully processed - no need to visit children. return false; } -void ForLoopUnroll::Push(TLoopIndexInfo& info) -{ - mLoopIndexStack.push_back(info); -} - -void ForLoopUnroll::Pop() +void ForLoopUnrollMarker::visitSymbol(TIntermSymbol* symbol) { - mLoopIndexStack.pop_back(); -} - -// static -void ForLoopUnroll::MarkForLoopsWithIntegerIndicesForUnrolling( - TIntermNode* root) -{ - ASSERT(root); - - IntegerForLoopUnrollMarker marker; - root->traverse(&marker); -} - -int ForLoopUnroll::getLoopIncrement(TIntermLoop* node) -{ - TIntermNode* expr = node->getExpression(); - ASSERT(expr != NULL); - // for expression has one of the following forms: - // loop_index++ - // loop_index-- - // loop_index += constant_expression - // loop_index -= constant_expression - // ++loop_index - // --loop_index - // The last two forms are not specified in the spec, but I am assuming - // its an oversight. - TIntermUnary* unOp = expr->getAsUnaryNode(); - TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode(); - - TOperator op = EOpNull; - TIntermConstantUnion* incrementNode = NULL; - if (unOp != NULL) { - op = unOp->getOp(); - } else if (binOp != NULL) { - op = binOp->getOp(); - ASSERT(binOp->getRight() != NULL); - incrementNode = binOp->getRight()->getAsConstantUnion(); - ASSERT(incrementNode != NULL); - } - - int increment = 0; - // The operator is one of: ++ -- += -=. - switch (op) { - case EOpPostIncrement: - case EOpPreIncrement: - ASSERT((unOp != NULL) && (binOp == NULL)); - increment = 1; - break; - case EOpPostDecrement: - case EOpPreDecrement: - ASSERT((unOp != NULL) && (binOp == NULL)); - increment = -1; - break; - case EOpAddAssign: - ASSERT((unOp == NULL) && (binOp != NULL)); - increment = evaluateIntConstant(incrementNode); + if (!mVisitSamplerArrayIndexNodeInsideLoop) + return; + TIntermLoop *loop = mLoopStack.findLoop(symbol); + if (loop) + { + switch (symbol->getBasicType()) + { + case EbtFloat: + mSamplerArrayIndexIsFloatLoopIndex = true; break; - case EOpSubAssign: - ASSERT((unOp == NULL) && (binOp != NULL)); - increment = - evaluateIntConstant(incrementNode); + case EbtInt: + loop->setUnrollFlag(true); break; - default: - ASSERT(false); + default: + UNREACHABLE(); + } } - - return increment; -} - -int ForLoopUnroll::evaluateIntConstant(TIntermConstantUnion* node) -{ - ASSERT((node != NULL) && (node->getUnionArrayPointer() != NULL)); - return node->getIConst(0); } - diff --git a/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h index afd70d1fd2..a820d2a20d 100644 --- a/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h +++ b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h @@ -7,46 +7,44 @@ #ifndef COMPILER_FORLOOPUNROLL_H_ #define COMPILER_FORLOOPUNROLL_H_ -#include "compiler/translator/intermediate.h" - -struct TLoopIndexInfo { - int id; - int initValue; - int stopValue; - int incrementValue; - TOperator op; - int currentValue; -}; - -class ForLoopUnroll { -public: - ForLoopUnroll() { } - - void FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info); - - // Update the info.currentValue for the next loop iteration. - void Step(); - - // Return false if loop condition is no longer satisfied. - bool SatisfiesLoopCondition(); - - // Check if the symbol is the index of a loop that's unrolled. - bool NeedsToReplaceSymbolWithValue(TIntermSymbol* symbol); - - // Return the current value of a given loop index symbol. - int GetLoopIndexValue(TIntermSymbol* symbol); - - void Push(TLoopIndexInfo& info); - void Pop(); - - static void MarkForLoopsWithIntegerIndicesForUnrolling(TIntermNode* root); - -private: - int getLoopIncrement(TIntermLoop* node); - - int evaluateIntConstant(TIntermConstantUnion* node); - - TVector mLoopIndexStack; +#include "compiler/translator/LoopInfo.h" + +// This class detects for-loops that needs to be unrolled. +// Currently we support two unroll conditions: +// 1) kForLoopWithIntegerIndex: unroll if the index type is integer. +// 2) kForLoopWithSamplerArrayIndex: unroll where a sampler array index +// is also the loop integer index, and reject and fail a compile +// where a sampler array index is also the loop float index. +class ForLoopUnrollMarker : public TIntermTraverser +{ + public: + enum UnrollCondition + { + kIntegerIndex, + kSamplerArrayIndex + }; + + ForLoopUnrollMarker(UnrollCondition condition) + : mUnrollCondition(condition), + mSamplerArrayIndexIsFloatLoopIndex(false), + mVisitSamplerArrayIndexNodeInsideLoop(false) + { + } + + virtual bool visitBinary(Visit, TIntermBinary *node); + virtual bool visitLoop(Visit, TIntermLoop *node); + virtual void visitSymbol(TIntermSymbol *node); + + bool samplerArrayIndexIsFloatLoopIndex() const + { + return mSamplerArrayIndexIsFloatLoopIndex; + } + + private: + UnrollCondition mUnrollCondition; + TLoopStack mLoopStack; + bool mSamplerArrayIndexIsFloatLoopIndex; + bool mVisitSamplerArrayIndexNodeInsideLoop; }; #endif diff --git a/src/3rdparty/angle/src/compiler/translator/HashNames.h b/src/3rdparty/angle/src/compiler/translator/HashNames.h index 751265b759..85161428b2 100644 --- a/src/3rdparty/angle/src/compiler/translator/HashNames.h +++ b/src/3rdparty/angle/src/compiler/translator/HashNames.h @@ -10,7 +10,6 @@ #include #include "compiler/translator/intermediate.h" -#include "GLSLANG/ShaderLang.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 db728b2129..e91d64f43b 100644 --- a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp @@ -1,11 +1,11 @@ // -// Copyright (c) 2002-2013 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. // // -// Create strings that declare built-in definitions, add built-ins that +// Create symbols that declare built-in definitions, add built-ins that // cannot be expressed in the files, and establish mappings between // built-in functions and operators. // @@ -13,412 +13,589 @@ #include "compiler/translator/Initialize.h" #include "compiler/translator/intermediate.h" +#include "angle_gl.h" -void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable) +void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable) { - TType *float1 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 1); - TType *float2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2); - TType *float3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3); - TType *float4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4); + TType *float1 = new TType(EbtFloat); + TType *float2 = new TType(EbtFloat, 2); + TType *float3 = new TType(EbtFloat, 3); + TType *float4 = new TType(EbtFloat, 4); - TType *int2 = new TType(EbtInt, EbpUndefined, EvqGlobal, 2); - TType *int3 = new TType(EbtInt, EbpUndefined, EvqGlobal, 3); - TType *int4 = new TType(EbtInt, EbpUndefined, EvqGlobal, 4); + TType *int1 = new TType(EbtInt); + TType *int2 = new TType(EbtInt, 2); + TType *int3 = new TType(EbtInt, 3); + TType *int4 = new TType(EbtInt, 4); // // Angle and Trigonometric Functions. // - symbolTable.insertBuiltIn(float1, "radians", float1); - symbolTable.insertBuiltIn(float2, "radians", float2); - symbolTable.insertBuiltIn(float3, "radians", float3); - symbolTable.insertBuiltIn(float4, "radians", float4); - - symbolTable.insertBuiltIn(float1, "degrees", float1); - symbolTable.insertBuiltIn(float2, "degrees", float2); - symbolTable.insertBuiltIn(float3, "degrees", float3); - symbolTable.insertBuiltIn(float4, "degrees", float4); - - symbolTable.insertBuiltIn(float1, "sin", float1); - symbolTable.insertBuiltIn(float2, "sin", float2); - symbolTable.insertBuiltIn(float3, "sin", float3); - symbolTable.insertBuiltIn(float4, "sin", float4); - - symbolTable.insertBuiltIn(float1, "cos", float1); - symbolTable.insertBuiltIn(float2, "cos", float2); - symbolTable.insertBuiltIn(float3, "cos", float3); - symbolTable.insertBuiltIn(float4, "cos", float4); - - symbolTable.insertBuiltIn(float1, "tan", float1); - symbolTable.insertBuiltIn(float2, "tan", float2); - symbolTable.insertBuiltIn(float3, "tan", float3); - symbolTable.insertBuiltIn(float4, "tan", float4); - - symbolTable.insertBuiltIn(float1, "asin", float1); - symbolTable.insertBuiltIn(float2, "asin", float2); - symbolTable.insertBuiltIn(float3, "asin", float3); - symbolTable.insertBuiltIn(float4, "asin", float4); - - symbolTable.insertBuiltIn(float1, "acos", float1); - symbolTable.insertBuiltIn(float2, "acos", float2); - symbolTable.insertBuiltIn(float3, "acos", float3); - symbolTable.insertBuiltIn(float4, "acos", float4); - - symbolTable.insertBuiltIn(float1, "atan", float1, float1); - symbolTable.insertBuiltIn(float2, "atan", float2, float2); - symbolTable.insertBuiltIn(float3, "atan", float3, float3); - symbolTable.insertBuiltIn(float4, "atan", float4, float4); - - symbolTable.insertBuiltIn(float1, "atan", float1); - symbolTable.insertBuiltIn(float2, "atan", float2); - symbolTable.insertBuiltIn(float3, "atan", float3); - symbolTable.insertBuiltIn(float4, "atan", float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "radians", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "radians", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "radians", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "radians", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "degrees", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "degrees", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "degrees", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "degrees", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "sin", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "sin", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "sin", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "sin", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "cos", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "cos", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "cos", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "cos", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "tan", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "tan", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "tan", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "tan", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "asin", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "asin", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "asin", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "asin", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "acos", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "acos", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "acos", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "acos", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "atan", float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "atan", float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "atan", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "atan", float4, float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "atan", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "atan", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "atan", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "atan", float4); // // Exponential Functions. // - symbolTable.insertBuiltIn(float1, "pow", float1, float1); - symbolTable.insertBuiltIn(float2, "pow", float2, float2); - symbolTable.insertBuiltIn(float3, "pow", float3, float3); - symbolTable.insertBuiltIn(float4, "pow", float4, float4); - - symbolTable.insertBuiltIn(float1, "exp", float1); - symbolTable.insertBuiltIn(float2, "exp", float2); - symbolTable.insertBuiltIn(float3, "exp", float3); - symbolTable.insertBuiltIn(float4, "exp", float4); - - symbolTable.insertBuiltIn(float1, "log", float1); - symbolTable.insertBuiltIn(float2, "log", float2); - symbolTable.insertBuiltIn(float3, "log", float3); - symbolTable.insertBuiltIn(float4, "log", float4); - - symbolTable.insertBuiltIn(float1, "exp2", float1); - symbolTable.insertBuiltIn(float2, "exp2", float2); - symbolTable.insertBuiltIn(float3, "exp2", float3); - symbolTable.insertBuiltIn(float4, "exp2", float4); - - symbolTable.insertBuiltIn(float1, "log2", float1); - symbolTable.insertBuiltIn(float2, "log2", float2); - symbolTable.insertBuiltIn(float3, "log2", float3); - symbolTable.insertBuiltIn(float4, "log2", float4); - - symbolTable.insertBuiltIn(float1, "sqrt", float1); - symbolTable.insertBuiltIn(float2, "sqrt", float2); - symbolTable.insertBuiltIn(float3, "sqrt", float3); - symbolTable.insertBuiltIn(float4, "sqrt", float4); - - symbolTable.insertBuiltIn(float1, "inversesqrt", float1); - symbolTable.insertBuiltIn(float2, "inversesqrt", float2); - symbolTable.insertBuiltIn(float3, "inversesqrt", float3); - symbolTable.insertBuiltIn(float4, "inversesqrt", float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "pow", float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "pow", float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "pow", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "pow", float4, float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "exp", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "exp", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "exp", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "exp", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "log", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "log", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "log", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "log", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "exp2", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "exp2", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "exp2", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "exp2", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "log2", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "log2", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "log2", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "log2", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "sqrt", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "sqrt", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "sqrt", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "sqrt", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "inversesqrt", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "inversesqrt", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "inversesqrt", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "inversesqrt", float4); // // Common Functions. // - symbolTable.insertBuiltIn(float1, "abs", float1); - symbolTable.insertBuiltIn(float2, "abs", float2); - symbolTable.insertBuiltIn(float3, "abs", float3); - symbolTable.insertBuiltIn(float4, "abs", float4); - - symbolTable.insertBuiltIn(float1, "sign", float1); - symbolTable.insertBuiltIn(float2, "sign", float2); - symbolTable.insertBuiltIn(float3, "sign", float3); - symbolTable.insertBuiltIn(float4, "sign", float4); - - symbolTable.insertBuiltIn(float1, "floor", float1); - symbolTable.insertBuiltIn(float2, "floor", float2); - symbolTable.insertBuiltIn(float3, "floor", float3); - symbolTable.insertBuiltIn(float4, "floor", float4); - - symbolTable.insertBuiltIn(float1, "ceil", float1); - symbolTable.insertBuiltIn(float2, "ceil", float2); - symbolTable.insertBuiltIn(float3, "ceil", float3); - symbolTable.insertBuiltIn(float4, "ceil", float4); - - symbolTable.insertBuiltIn(float1, "fract", float1); - symbolTable.insertBuiltIn(float2, "fract", float2); - symbolTable.insertBuiltIn(float3, "fract", float3); - symbolTable.insertBuiltIn(float4, "fract", float4); - - symbolTable.insertBuiltIn(float1, "mod", float1, float1); - symbolTable.insertBuiltIn(float2, "mod", float2, float1); - symbolTable.insertBuiltIn(float3, "mod", float3, float1); - symbolTable.insertBuiltIn(float4, "mod", float4, float1); - symbolTable.insertBuiltIn(float2, "mod", float2, float2); - symbolTable.insertBuiltIn(float3, "mod", float3, float3); - symbolTable.insertBuiltIn(float4, "mod", float4, float4); - - symbolTable.insertBuiltIn(float1, "min", float1, float1); - symbolTable.insertBuiltIn(float2, "min", float2, float1); - symbolTable.insertBuiltIn(float3, "min", float3, float1); - symbolTable.insertBuiltIn(float4, "min", float4, float1); - symbolTable.insertBuiltIn(float2, "min", float2, float2); - symbolTable.insertBuiltIn(float3, "min", float3, float3); - symbolTable.insertBuiltIn(float4, "min", float4, float4); - - symbolTable.insertBuiltIn(float1, "max", float1, float1); - symbolTable.insertBuiltIn(float2, "max", float2, float1); - symbolTable.insertBuiltIn(float3, "max", float3, float1); - symbolTable.insertBuiltIn(float4, "max", float4, float1); - symbolTable.insertBuiltIn(float2, "max", float2, float2); - symbolTable.insertBuiltIn(float3, "max", float3, float3); - symbolTable.insertBuiltIn(float4, "max", float4, float4); - - symbolTable.insertBuiltIn(float1, "clamp", float1, float1, float1); - symbolTable.insertBuiltIn(float2, "clamp", float2, float1, float1); - symbolTable.insertBuiltIn(float3, "clamp", float3, float1, float1); - symbolTable.insertBuiltIn(float4, "clamp", float4, float1, float1); - symbolTable.insertBuiltIn(float2, "clamp", float2, float2, float2); - symbolTable.insertBuiltIn(float3, "clamp", float3, float3, float3); - symbolTable.insertBuiltIn(float4, "clamp", float4, float4, float4); - - symbolTable.insertBuiltIn(float1, "mix", float1, float1, float1); - symbolTable.insertBuiltIn(float2, "mix", float2, float2, float1); - symbolTable.insertBuiltIn(float3, "mix", float3, float3, float1); - symbolTable.insertBuiltIn(float4, "mix", float4, float4, float1); - symbolTable.insertBuiltIn(float2, "mix", float2, float2, float2); - symbolTable.insertBuiltIn(float3, "mix", float3, float3, float3); - symbolTable.insertBuiltIn(float4, "mix", float4, float4, float4); - - symbolTable.insertBuiltIn(float1, "step", float1, float1); - symbolTable.insertBuiltIn(float2, "step", float2, float2); - symbolTable.insertBuiltIn(float3, "step", float3, float3); - symbolTable.insertBuiltIn(float4, "step", float4, float4); - symbolTable.insertBuiltIn(float2, "step", float1, float2); - symbolTable.insertBuiltIn(float3, "step", float1, float3); - symbolTable.insertBuiltIn(float4, "step", float1, float4); - - symbolTable.insertBuiltIn(float1, "smoothstep", float1, float1, float1); - symbolTable.insertBuiltIn(float2, "smoothstep", float2, float2, float2); - symbolTable.insertBuiltIn(float3, "smoothstep", float3, float3, float3); - symbolTable.insertBuiltIn(float4, "smoothstep", float4, float4, float4); - symbolTable.insertBuiltIn(float2, "smoothstep", float1, float1, float2); - symbolTable.insertBuiltIn(float3, "smoothstep", float1, float1, float3); - symbolTable.insertBuiltIn(float4, "smoothstep", float1, float1, float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "abs", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "abs", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "abs", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "abs", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "sign", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "sign", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "sign", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "sign", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "floor", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "floor", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "floor", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "floor", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "ceil", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "ceil", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "ceil", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "ceil", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "fract", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "fract", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "fract", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "fract", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "mod", float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mod", float2, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mod", float3, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mod", float4, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mod", float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mod", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mod", float4, float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "min", float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "min", float2, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "min", float3, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "min", float4, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "min", float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "min", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "min", float4, float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "max", float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "max", float2, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "max", float3, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "max", float4, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "max", float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "max", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "max", float4, float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "clamp", float1, float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "clamp", float2, float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "clamp", float3, float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "clamp", float4, float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "clamp", float2, float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "clamp", float3, float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "clamp", float4, float4, float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "mix", float1, float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mix", float2, float2, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mix", float3, float3, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mix", float4, float4, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mix", float2, float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mix", float3, float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mix", float4, float4, float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "step", float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "step", float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "step", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "step", float4, float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "step", float1, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "step", float1, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "step", float1, float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "smoothstep", float1, float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "smoothstep", float2, float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "smoothstep", float3, float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "smoothstep", float4, float4, float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "smoothstep", float1, float1, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "smoothstep", float1, float1, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "smoothstep", float1, float1, float4); // // Geometric Functions. // - symbolTable.insertBuiltIn(float1, "length", float1); - symbolTable.insertBuiltIn(float1, "length", float2); - symbolTable.insertBuiltIn(float1, "length", float3); - symbolTable.insertBuiltIn(float1, "length", float4); - - symbolTable.insertBuiltIn(float1, "distance", float1, float1); - symbolTable.insertBuiltIn(float1, "distance", float2, float2); - symbolTable.insertBuiltIn(float1, "distance", float3, float3); - symbolTable.insertBuiltIn(float1, "distance", float4, float4); - - symbolTable.insertBuiltIn(float1, "dot", float1, float1); - symbolTable.insertBuiltIn(float1, "dot", float2, float2); - symbolTable.insertBuiltIn(float1, "dot", float3, float3); - symbolTable.insertBuiltIn(float1, "dot", float4, float4); - - symbolTable.insertBuiltIn(float3, "cross", float3, float3); - symbolTable.insertBuiltIn(float1, "normalize", float1); - symbolTable.insertBuiltIn(float2, "normalize", float2); - symbolTable.insertBuiltIn(float3, "normalize", float3); - symbolTable.insertBuiltIn(float4, "normalize", float4); - - symbolTable.insertBuiltIn(float1, "faceforward", float1, float1, float1); - symbolTable.insertBuiltIn(float2, "faceforward", float2, float2, float2); - symbolTable.insertBuiltIn(float3, "faceforward", float3, float3, float3); - symbolTable.insertBuiltIn(float4, "faceforward", float4, float4, float4); - - symbolTable.insertBuiltIn(float1, "reflect", float1, float1); - symbolTable.insertBuiltIn(float2, "reflect", float2, float2); - symbolTable.insertBuiltIn(float3, "reflect", float3, float3); - symbolTable.insertBuiltIn(float4, "reflect", float4, float4); - - symbolTable.insertBuiltIn(float1, "refract", float1, float1, float1); - symbolTable.insertBuiltIn(float2, "refract", float2, float2, float1); - symbolTable.insertBuiltIn(float3, "refract", float3, float3, float1); - symbolTable.insertBuiltIn(float4, "refract", float4, float4, float1); - - TType *mat2 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 2, true); - TType *mat3 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 3, true); - TType *mat4 = new TType(EbtFloat, EbpUndefined, EvqGlobal, 4, true); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float4, float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float4, float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "cross", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "normalize", float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "normalize", float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "normalize", float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "normalize", float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "faceforward", float1, float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "faceforward", float2, float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "faceforward", float3, float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "faceforward", float4, float4, float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "reflect", float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "reflect", float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "reflect", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "reflect", float4, float4); + + symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "refract", float1, float1, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "refract", float2, float2, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "refract", float3, float3, float1); + symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "refract", float4, float4, float1); + + TType *mat2 = new TType(EbtFloat, 2, 2); + TType *mat3 = new TType(EbtFloat, 3, 3); + TType *mat4 = new TType(EbtFloat, 4, 4); // // Matrix Functions. // - symbolTable.insertBuiltIn(mat2, "matrixCompMult", mat2, mat2); - symbolTable.insertBuiltIn(mat3, "matrixCompMult", mat3, mat3); - symbolTable.insertBuiltIn(mat4, "matrixCompMult", mat4, mat4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, mat2, "matrixCompMult", mat2, mat2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, mat3, "matrixCompMult", mat3, mat3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, mat4, "matrixCompMult", mat4, mat4); - TType *bool1 = new TType(EbtBool, EbpUndefined, EvqGlobal, 1); - TType *bool2 = new TType(EbtBool, EbpUndefined, EvqGlobal, 2); - TType *bool3 = new TType(EbtBool, EbpUndefined, EvqGlobal, 3); - TType *bool4 = new TType(EbtBool, EbpUndefined, EvqGlobal, 4); + TType *bool1 = new TType(EbtBool); + TType *bool2 = new TType(EbtBool, 2); + TType *bool3 = new TType(EbtBool, 3); + TType *bool4 = new TType(EbtBool, 4); // // Vector relational functions. // - symbolTable.insertBuiltIn(bool2, "lessThan", float2, float2); - symbolTable.insertBuiltIn(bool3, "lessThan", float3, float3); - symbolTable.insertBuiltIn(bool4, "lessThan", float4, float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThan", float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThan", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThan", float4, float4); - symbolTable.insertBuiltIn(bool2, "lessThan", int2, int2); - symbolTable.insertBuiltIn(bool3, "lessThan", int3, int3); - symbolTable.insertBuiltIn(bool4, "lessThan", int4, int4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThan", int2, int2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThan", int3, int3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThan", int4, int4); - symbolTable.insertBuiltIn(bool2, "lessThanEqual", float2, float2); - symbolTable.insertBuiltIn(bool3, "lessThanEqual", float3, float3); - symbolTable.insertBuiltIn(bool4, "lessThanEqual", float4, float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThanEqual", float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThanEqual", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThanEqual", float4, float4); - symbolTable.insertBuiltIn(bool2, "lessThanEqual", int2, int2); - symbolTable.insertBuiltIn(bool3, "lessThanEqual", int3, int3); - symbolTable.insertBuiltIn(bool4, "lessThanEqual", int4, int4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThanEqual", int2, int2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThanEqual", int3, int3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThanEqual", int4, int4); - symbolTable.insertBuiltIn(bool2, "greaterThan", float2, float2); - symbolTable.insertBuiltIn(bool3, "greaterThan", float3, float3); - symbolTable.insertBuiltIn(bool4, "greaterThan", float4, float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThan", float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThan", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThan", float4, float4); - symbolTable.insertBuiltIn(bool2, "greaterThan", int2, int2); - symbolTable.insertBuiltIn(bool3, "greaterThan", int3, int3); - symbolTable.insertBuiltIn(bool4, "greaterThan", int4, int4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThan", int2, int2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThan", int3, int3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThan", int4, int4); - symbolTable.insertBuiltIn(bool2, "greaterThanEqual", float2, float2); - symbolTable.insertBuiltIn(bool3, "greaterThanEqual", float3, float3); - symbolTable.insertBuiltIn(bool4, "greaterThanEqual", float4, float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThanEqual", float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThanEqual", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThanEqual", float4, float4); - symbolTable.insertBuiltIn(bool2, "greaterThanEqual", int2, int2); - symbolTable.insertBuiltIn(bool3, "greaterThanEqual", int3, int3); - symbolTable.insertBuiltIn(bool4, "greaterThanEqual", int4, int4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThanEqual", int2, int2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThanEqual", int3, int3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThanEqual", int4, int4); - symbolTable.insertBuiltIn(bool2, "equal", float2, float2); - symbolTable.insertBuiltIn(bool3, "equal", float3, float3); - symbolTable.insertBuiltIn(bool4, "equal", float4, float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "equal", float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "equal", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "equal", float4, float4); - symbolTable.insertBuiltIn(bool2, "equal", int2, int2); - symbolTable.insertBuiltIn(bool3, "equal", int3, int3); - symbolTable.insertBuiltIn(bool4, "equal", int4, int4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "equal", int2, int2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "equal", int3, int3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "equal", int4, int4); - symbolTable.insertBuiltIn(bool2, "equal", bool2, bool2); - symbolTable.insertBuiltIn(bool3, "equal", bool3, bool3); - symbolTable.insertBuiltIn(bool4, "equal", bool4, bool4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "equal", bool2, bool2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "equal", bool3, bool3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "equal", bool4, bool4); - symbolTable.insertBuiltIn(bool2, "notEqual", float2, float2); - symbolTable.insertBuiltIn(bool3, "notEqual", float3, float3); - symbolTable.insertBuiltIn(bool4, "notEqual", float4, float4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "notEqual", float2, float2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "notEqual", float3, float3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "notEqual", float4, float4); - symbolTable.insertBuiltIn(bool2, "notEqual", int2, int2); - symbolTable.insertBuiltIn(bool3, "notEqual", int3, int3); - symbolTable.insertBuiltIn(bool4, "notEqual", int4, int4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "notEqual", int2, int2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "notEqual", int3, int3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "notEqual", int4, int4); - symbolTable.insertBuiltIn(bool2, "notEqual", bool2, bool2); - symbolTable.insertBuiltIn(bool3, "notEqual", bool3, bool3); - symbolTable.insertBuiltIn(bool4, "notEqual", bool4, bool4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "notEqual", bool2, bool2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "notEqual", bool3, bool3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "notEqual", bool4, bool4); - symbolTable.insertBuiltIn(bool1, "any", bool2); - symbolTable.insertBuiltIn(bool1, "any", bool3); - symbolTable.insertBuiltIn(bool1, "any", bool4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "any", bool2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "any", bool3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "any", bool4); - symbolTable.insertBuiltIn(bool1, "all", bool2); - symbolTable.insertBuiltIn(bool1, "all", bool3); - symbolTable.insertBuiltIn(bool1, "all", bool4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "all", bool2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "all", bool3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "all", bool4); - symbolTable.insertBuiltIn(bool2, "not", bool2); - symbolTable.insertBuiltIn(bool3, "not", bool3); - symbolTable.insertBuiltIn(bool4, "not", bool4); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "not", bool2); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "not", bool3); + symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "not", bool4); - TType *sampler2D = new TType(EbtSampler2D, EbpUndefined, EvqGlobal, 1); - TType *samplerCube = new TType(EbtSamplerCube, EbpUndefined, EvqGlobal, 1); + TType *sampler2D = new TType(EbtSampler2D); + TType *samplerCube = new TType(EbtSamplerCube); // // Texture Functions for GLSL ES 1.0 // - symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2); - symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3); - symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4); - symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3); if (resources.OES_EGL_image_external) { - TType *samplerExternalOES = new TType(EbtSamplerExternalOES, EbpUndefined, EvqGlobal, 1); + TType *samplerExternalOES = new TType(EbtSamplerExternalOES); - symbolTable.insertBuiltIn(float4, "texture2D", samplerExternalOES, float2); - symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float3); - symbolTable.insertBuiltIn(float4, "texture2DProj", samplerExternalOES, float4); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", samplerExternalOES, float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES, float3); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", samplerExternalOES, float4); } if (resources.ARB_texture_rectangle) { - TType *sampler2DRect = new TType(EbtSampler2DRect, EbpUndefined, EvqGlobal, 1); + TType *sampler2DRect = new TType(EbtSampler2DRect); - symbolTable.insertBuiltIn(float4, "texture2DRect", sampler2DRect, float2); - symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float3); - symbolTable.insertBuiltIn(float4, "texture2DRectProj", sampler2DRect, float4); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRect", sampler2DRect, float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRectProj", sampler2DRect, float3); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DRectProj", sampler2DRect, float4); } - if (type == SH_FRAGMENT_SHADER) + if (resources.EXT_shader_texture_lod) { - symbolTable.insertBuiltIn(float4, "texture2D", sampler2D, float2, float1); - symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float3, float1); - symbolTable.insertBuiltIn(float4, "texture2DProj", sampler2D, float4, float1); - symbolTable.insertBuiltIn(float4, "textureCube", samplerCube, float3, float1); + /* The *Grad* variants are new to both vertex and fragment shaders; the fragment + * shader specific pieces are added separately below. + */ + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DGradEXT", sampler2D, float2, float2, float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjGradEXT", sampler2D, float3, float2, float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjGradEXT", sampler2D, float4, float2, float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeGradEXT", samplerCube, float3, float3, float3); + } + + if (type == GL_FRAGMENT_SHADER) + { + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2D", sampler2D, float2, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float3, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProj", sampler2D, float4, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCube", samplerCube, float3, float1); if (resources.OES_standard_derivatives) { - symbolTable.insertBuiltIn(float1, "dFdx", float1); - symbolTable.insertBuiltIn(float2, "dFdx", float2); - symbolTable.insertBuiltIn(float3, "dFdx", float3); - symbolTable.insertBuiltIn(float4, "dFdx", float4); - - symbolTable.insertBuiltIn(float1, "dFdy", float1); - symbolTable.insertBuiltIn(float2, "dFdy", float2); - symbolTable.insertBuiltIn(float3, "dFdy", float3); - symbolTable.insertBuiltIn(float4, "dFdy", float4); - - symbolTable.insertBuiltIn(float1, "fwidth", float1); - symbolTable.insertBuiltIn(float2, "fwidth", float2); - symbolTable.insertBuiltIn(float3, "fwidth", float3); - symbolTable.insertBuiltIn(float4, "fwidth", float4); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float1, "dFdx", float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "dFdx", float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "dFdx", float3); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "dFdx", float4); + + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float1, "dFdy", float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "dFdy", float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "dFdy", float3); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "dFdy", float4); + + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float1, "fwidth", float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "fwidth", float2); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "fwidth", float3); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "fwidth", float4); + } + + if (resources.EXT_shader_texture_lod) + { + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLodEXT", sampler2D, float2, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLodEXT", sampler2D, float3, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLodEXT", sampler2D, float4, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeLodEXT", samplerCube, float3, float1); } } - if(type == SH_VERTEX_SHADER) + if(type == GL_VERTEX_SHADER) { - symbolTable.insertBuiltIn(float4, "texture2DLod", sampler2D, float2, float1); - symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float3, float1); - symbolTable.insertBuiltIn(float4, "texture2DProjLod", sampler2D, float4, float1); - symbolTable.insertBuiltIn(float4, "textureCubeLod", samplerCube, float3, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLod", sampler2D, float2, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float3, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float4, float1); + symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeLod", samplerCube, float3, float1); } + TType *gvec4 = new TType(EbtGVec4); + + TType *gsampler2D = new TType(EbtGSampler2D); + TType *gsamplerCube = new TType(EbtGSamplerCube); + TType *gsampler3D = new TType(EbtGSampler3D); + TType *gsampler2DArray = new TType(EbtGSampler2DArray); + + // + // Texture Functions for GLSL ES 3.0 + // + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler3D, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsamplerCube, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2DArray, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2D, float2, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler3D, float3, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsamplerCube, float3, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLod", gsampler2DArray, float3, float1); + + if (type == GL_FRAGMENT_SHADER) + { + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2D, float2, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler3D, float3, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsamplerCube, float3, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texture", gsampler2DArray, float3, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float3, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler2D, float4, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProj", gsampler3D, float4, float1); + } + + TType *sampler2DShadow = new TType(EbtSampler2DShadow); + TType *samplerCubeShadow = new TType(EbtSamplerCubeShadow); + TType *sampler2DArrayShadow = new TType(EbtSampler2DArrayShadow); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DShadow, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", samplerCubeShadow, float4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DArrayShadow, float4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProj", sampler2DShadow, float4); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureLod", sampler2DShadow, float3, float1); + + if (type == GL_FRAGMENT_SHADER) + { + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", sampler2DShadow, float3, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "texture", samplerCubeShadow, float4, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProj", sampler2DShadow, float4, float1); + } + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", gsampler2D, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", gsampler3D, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", gsamplerCube, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", gsampler2DArray, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", sampler2DShadow, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerCubeShadow, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", sampler2DArrayShadow, int1); + + if(type == GL_FRAGMENT_SHADER) + { + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "dFdx", float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "dFdx", float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "dFdx", float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "dFdx", float4); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "dFdy", float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "dFdy", float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "dFdy", float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "dFdy", float4); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "fwidth", float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "fwidth", float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "fwidth", float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "fwidth", float4); + } + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3, int2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3, int2); + + if(type == GL_FRAGMENT_SHADER) + { + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3, int2, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3, int2, float1); + } + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3, int2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4, int2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4, int3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow, float4, int2); + + if(type == GL_FRAGMENT_SHADER) + { + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3, int2, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4, int2, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4, int3, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow, float4, int2, float1); + } + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler2D, float2, float1, int2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler3D, float3, float1, int3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureLodOffset", sampler2DShadow, float3, float1, int2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureLodOffset", gsampler2DArray, float3, float1, int2); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler2D, float3, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler2D, float4, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLod", gsampler3D, float4, float1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjLod", sampler2DShadow, float4, float1); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler2D, float3, float1, int2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler2D, float4, float1, int2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjLodOffset", gsampler3D, float4, float1, int3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjLodOffset", sampler2DShadow, float4, float1, int2); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler2D, int2, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler3D, int3, int1); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetch", gsampler2DArray, int3, int1); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2D, int2, int1, int2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler3D, int3, int1, int3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "texelFetchOffset", gsampler2DArray, int3, int1, int2); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler2D, float2, float2, float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler3D, float3, float3, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsamplerCube, float3, float3, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", sampler2DShadow, float3, float2, float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", samplerCubeShadow, float4, float3, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGrad", gsampler2DArray, float3, float2, float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGrad", sampler2DArrayShadow, float4, float2, float2); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler2D, float2, float2, float2, int2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler3D, float3, float3, float3, int3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGradOffset", sampler2DShadow, float3, float2, float2, int2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureGradOffset", gsampler2DArray, float3, float2, float2, int2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureGradOffset", sampler2DArrayShadow, float4, float2, float2, int2); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler2D, float3, float2, float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler2D, float4, float2, float2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGrad", gsampler3D, float4, float3, float3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGrad", sampler2DShadow, float4, float2, float2); + + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler2D, float3, float2, float2, int2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler2D, float4, float2, float2, int2); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjGradOffset", gsampler3D, float4, float3, float3, int3); + symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjGradOffset", sampler2DShadow, float4, float2, float2, int2); + // // Depth range in window coordinates // TFieldList *fields = NewPoolTFieldList(); - TField *near = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("near")); - TField *far = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("far")); - TField *diff = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("diff")); + TSourceLoc zeroSourceLoc = {0, 0, 0, 0}; + TField *near = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("near"), zeroSourceLoc); + TField *far = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("far"), zeroSourceLoc); + TField *diff = new TField(new TType(EbtFloat, EbpHigh, EvqGlobal, 1), NewPoolTString("diff"), zeroSourceLoc); fields->push_back(near); fields->push_back(far); fields->push_back(diff); TStructure *depthRangeStruct = new TStructure(NewPoolTString("gl_DepthRangeParameters"), fields); TVariable *depthRangeParameters = new TVariable(&depthRangeStruct->name(), depthRangeStruct, true); - symbolTable.insert(*depthRangeParameters); + symbolTable.insert(COMMON_BUILTINS, depthRangeParameters); TVariable *depthRange = new TVariable(NewPoolTString("gl_DepthRange"), TType(depthRangeStruct)); depthRange->setQualifier(EvqUniform); - symbolTable.insert(*depthRange); + symbolTable.insert(COMMON_BUILTINS, depthRange); // // Implementation dependent built-in constants. // - symbolTable.insertConstInt("gl_MaxVertexAttribs", resources.MaxVertexAttribs); - symbolTable.insertConstInt("gl_MaxVertexUniformVectors", resources.MaxVertexUniformVectors); - symbolTable.insertConstInt("gl_MaxVaryingVectors", resources.MaxVaryingVectors); - symbolTable.insertConstInt("gl_MaxVertexTextureImageUnits", resources.MaxVertexTextureImageUnits); - symbolTable.insertConstInt("gl_MaxCombinedTextureImageUnits", resources.MaxCombinedTextureImageUnits); - symbolTable.insertConstInt("gl_MaxTextureImageUnits", resources.MaxTextureImageUnits); - symbolTable.insertConstInt("gl_MaxFragmentUniformVectors", resources.MaxFragmentUniformVectors); + symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexAttribs", resources.MaxVertexAttribs); + symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexUniformVectors", resources.MaxVertexUniformVectors); + symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxVertexTextureImageUnits", resources.MaxVertexTextureImageUnits); + symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxCombinedTextureImageUnits", resources.MaxCombinedTextureImageUnits); + symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxTextureImageUnits", resources.MaxTextureImageUnits); + symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxFragmentUniformVectors", resources.MaxFragmentUniformVectors); + + symbolTable.insertConstInt(ESSL1_BUILTINS, "gl_MaxVaryingVectors", resources.MaxVaryingVectors); if (spec != SH_CSS_SHADERS_SPEC) { - symbolTable.insertConstInt("gl_MaxDrawBuffers", resources.MaxDrawBuffers); + symbolTable.insertConstInt(COMMON_BUILTINS, "gl_MaxDrawBuffers", resources.MaxDrawBuffers); } + + symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxVertexOutputVectors", resources.MaxVertexOutputVectors); + symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxFragmentInputVectors", resources.MaxFragmentInputVectors); + symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MinProgramTexelOffset", resources.MinProgramTexelOffset); + symbolTable.insertConstInt(ESSL3_BUILTINS, "gl_MaxProgramTexelOffset", resources.MaxProgramTexelOffset); } -void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, +void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &symbolTable) { @@ -427,32 +604,32 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, // the built-in header files. // switch(type) { - case SH_FRAGMENT_SHADER: - symbolTable.insert(*new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4))); - symbolTable.insert(*new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1))); - symbolTable.insert(*new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); + case GL_FRAGMENT_SHADER: + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4))); + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1))); + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2))); // // In CSS Shaders, gl_FragColor, gl_FragData, and gl_MaxDrawBuffers are not available. // Instead, css_MixColor and css_ColorMatrix are available. // if (spec != SH_CSS_SHADERS_SPEC) { - symbolTable.insert(*new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4))); - symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4))); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4))); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4))); if (resources.EXT_frag_depth) { - symbolTable.insert(*new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1))); - symbolTable.relateToExtension("gl_FragDepthEXT", "GL_EXT_frag_depth"); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1))); + symbolTable.relateToExtension(ESSL1_BUILTINS, "gl_FragDepthEXT", "GL_EXT_frag_depth"); } } else { - symbolTable.insert(*new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4))); - symbolTable.insert(*new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, true))); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4))); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, 4))); } break; - case SH_VERTEX_SHADER: - symbolTable.insert(*new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4))); - symbolTable.insert(*new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize, 1))); + case GL_VERTEX_SHADER: + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4))); + symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize, 1))); break; default: assert(false && "Language not supported"); @@ -464,84 +641,102 @@ void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, // expected to be resolved through a library of functions, versus as // operations. // - symbolTable.relateToOperator("matrixCompMult", EOpMul); - - symbolTable.relateToOperator("equal", EOpVectorEqual); - symbolTable.relateToOperator("notEqual", EOpVectorNotEqual); - symbolTable.relateToOperator("lessThan", EOpLessThan); - symbolTable.relateToOperator("greaterThan", EOpGreaterThan); - symbolTable.relateToOperator("lessThanEqual", EOpLessThanEqual); - symbolTable.relateToOperator("greaterThanEqual", EOpGreaterThanEqual); - - symbolTable.relateToOperator("radians", EOpRadians); - symbolTable.relateToOperator("degrees", EOpDegrees); - symbolTable.relateToOperator("sin", EOpSin); - symbolTable.relateToOperator("cos", EOpCos); - symbolTable.relateToOperator("tan", EOpTan); - symbolTable.relateToOperator("asin", EOpAsin); - symbolTable.relateToOperator("acos", EOpAcos); - symbolTable.relateToOperator("atan", EOpAtan); - - symbolTable.relateToOperator("pow", EOpPow); - symbolTable.relateToOperator("exp2", EOpExp2); - symbolTable.relateToOperator("log", EOpLog); - symbolTable.relateToOperator("exp", EOpExp); - symbolTable.relateToOperator("log2", EOpLog2); - symbolTable.relateToOperator("sqrt", EOpSqrt); - symbolTable.relateToOperator("inversesqrt", EOpInverseSqrt); - - symbolTable.relateToOperator("abs", EOpAbs); - symbolTable.relateToOperator("sign", EOpSign); - symbolTable.relateToOperator("floor", EOpFloor); - symbolTable.relateToOperator("ceil", EOpCeil); - symbolTable.relateToOperator("fract", EOpFract); - symbolTable.relateToOperator("mod", EOpMod); - symbolTable.relateToOperator("min", EOpMin); - symbolTable.relateToOperator("max", EOpMax); - symbolTable.relateToOperator("clamp", EOpClamp); - symbolTable.relateToOperator("mix", EOpMix); - symbolTable.relateToOperator("step", EOpStep); - symbolTable.relateToOperator("smoothstep", EOpSmoothStep); - - symbolTable.relateToOperator("length", EOpLength); - symbolTable.relateToOperator("distance", EOpDistance); - symbolTable.relateToOperator("dot", EOpDot); - symbolTable.relateToOperator("cross", EOpCross); - symbolTable.relateToOperator("normalize", EOpNormalize); - symbolTable.relateToOperator("faceforward", EOpFaceForward); - symbolTable.relateToOperator("reflect", EOpReflect); - symbolTable.relateToOperator("refract", EOpRefract); + symbolTable.relateToOperator(COMMON_BUILTINS, "matrixCompMult", EOpMul); + + symbolTable.relateToOperator(COMMON_BUILTINS, "equal", EOpVectorEqual); + symbolTable.relateToOperator(COMMON_BUILTINS, "notEqual", EOpVectorNotEqual); + symbolTable.relateToOperator(COMMON_BUILTINS, "lessThan", EOpLessThan); + symbolTable.relateToOperator(COMMON_BUILTINS, "greaterThan", EOpGreaterThan); + symbolTable.relateToOperator(COMMON_BUILTINS, "lessThanEqual", EOpLessThanEqual); + symbolTable.relateToOperator(COMMON_BUILTINS, "greaterThanEqual", EOpGreaterThanEqual); - symbolTable.relateToOperator("any", EOpAny); - symbolTable.relateToOperator("all", EOpAll); - symbolTable.relateToOperator("not", EOpVectorLogicalNot); + symbolTable.relateToOperator(COMMON_BUILTINS, "radians", EOpRadians); + symbolTable.relateToOperator(COMMON_BUILTINS, "degrees", EOpDegrees); + symbolTable.relateToOperator(COMMON_BUILTINS, "sin", EOpSin); + symbolTable.relateToOperator(COMMON_BUILTINS, "cos", EOpCos); + symbolTable.relateToOperator(COMMON_BUILTINS, "tan", EOpTan); + symbolTable.relateToOperator(COMMON_BUILTINS, "asin", EOpAsin); + symbolTable.relateToOperator(COMMON_BUILTINS, "acos", EOpAcos); + symbolTable.relateToOperator(COMMON_BUILTINS, "atan", EOpAtan); + + symbolTable.relateToOperator(COMMON_BUILTINS, "pow", EOpPow); + symbolTable.relateToOperator(COMMON_BUILTINS, "exp2", EOpExp2); + symbolTable.relateToOperator(COMMON_BUILTINS, "log", EOpLog); + symbolTable.relateToOperator(COMMON_BUILTINS, "exp", EOpExp); + symbolTable.relateToOperator(COMMON_BUILTINS, "log2", EOpLog2); + symbolTable.relateToOperator(COMMON_BUILTINS, "sqrt", EOpSqrt); + symbolTable.relateToOperator(COMMON_BUILTINS, "inversesqrt", EOpInverseSqrt); + + symbolTable.relateToOperator(COMMON_BUILTINS, "abs", EOpAbs); + symbolTable.relateToOperator(COMMON_BUILTINS, "sign", EOpSign); + symbolTable.relateToOperator(COMMON_BUILTINS, "floor", EOpFloor); + symbolTable.relateToOperator(COMMON_BUILTINS, "ceil", EOpCeil); + symbolTable.relateToOperator(COMMON_BUILTINS, "fract", EOpFract); + symbolTable.relateToOperator(COMMON_BUILTINS, "mod", EOpMod); + symbolTable.relateToOperator(COMMON_BUILTINS, "min", EOpMin); + symbolTable.relateToOperator(COMMON_BUILTINS, "max", EOpMax); + symbolTable.relateToOperator(COMMON_BUILTINS, "clamp", EOpClamp); + symbolTable.relateToOperator(COMMON_BUILTINS, "mix", EOpMix); + symbolTable.relateToOperator(COMMON_BUILTINS, "step", EOpStep); + symbolTable.relateToOperator(COMMON_BUILTINS, "smoothstep", EOpSmoothStep); + + symbolTable.relateToOperator(COMMON_BUILTINS, "length", EOpLength); + symbolTable.relateToOperator(COMMON_BUILTINS, "distance", EOpDistance); + symbolTable.relateToOperator(COMMON_BUILTINS, "dot", EOpDot); + symbolTable.relateToOperator(COMMON_BUILTINS, "cross", EOpCross); + symbolTable.relateToOperator(COMMON_BUILTINS, "normalize", EOpNormalize); + symbolTable.relateToOperator(COMMON_BUILTINS, "faceforward", EOpFaceForward); + symbolTable.relateToOperator(COMMON_BUILTINS, "reflect", EOpReflect); + symbolTable.relateToOperator(COMMON_BUILTINS, "refract", EOpRefract); + + symbolTable.relateToOperator(COMMON_BUILTINS, "any", EOpAny); + symbolTable.relateToOperator(COMMON_BUILTINS, "all", EOpAll); + symbolTable.relateToOperator(COMMON_BUILTINS, "not", EOpVectorLogicalNot); // Map language-specific operators. switch(type) { - case SH_VERTEX_SHADER: + case GL_VERTEX_SHADER: break; - case SH_FRAGMENT_SHADER: - if (resources.OES_standard_derivatives) { - symbolTable.relateToOperator("dFdx", EOpDFdx); - symbolTable.relateToOperator("dFdy", EOpDFdy); - symbolTable.relateToOperator("fwidth", EOpFwidth); - - symbolTable.relateToExtension("dFdx", "GL_OES_standard_derivatives"); - symbolTable.relateToExtension("dFdy", "GL_OES_standard_derivatives"); - symbolTable.relateToExtension("fwidth", "GL_OES_standard_derivatives"); + case GL_FRAGMENT_SHADER: + if (resources.OES_standard_derivatives) + { + symbolTable.relateToOperator(ESSL1_BUILTINS, "dFdx", EOpDFdx); + symbolTable.relateToOperator(ESSL1_BUILTINS, "dFdy", EOpDFdy); + symbolTable.relateToOperator(ESSL1_BUILTINS, "fwidth", EOpFwidth); + + symbolTable.relateToExtension(ESSL1_BUILTINS, "dFdx", "GL_OES_standard_derivatives"); + symbolTable.relateToExtension(ESSL1_BUILTINS, "dFdy", "GL_OES_standard_derivatives"); + symbolTable.relateToExtension(ESSL1_BUILTINS, "fwidth", "GL_OES_standard_derivatives"); + } + if (resources.EXT_shader_texture_lod) + { + symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DLodEXT", "GL_EXT_shader_texture_lod"); + symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DProjLodEXT", "GL_EXT_shader_texture_lod"); + symbolTable.relateToExtension(ESSL1_BUILTINS, "textureCubeLodEXT", "GL_EXT_shader_texture_lod"); } break; default: break; } + symbolTable.relateToOperator(ESSL3_BUILTINS, "dFdx", EOpDFdx); + symbolTable.relateToOperator(ESSL3_BUILTINS, "dFdy", EOpDFdy); + symbolTable.relateToOperator(ESSL3_BUILTINS, "fwidth", EOpFwidth); + + if (resources.EXT_shader_texture_lod) + { + symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DGradEXT", "GL_EXT_shader_texture_lod"); + symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DProjGradEXT", "GL_EXT_shader_texture_lod"); + symbolTable.relateToExtension(ESSL1_BUILTINS, "textureCubeGradEXT", "GL_EXT_shader_texture_lod"); + } + // Finally add resource-specific variables. switch(type) { - case SH_FRAGMENT_SHADER: + case GL_FRAGMENT_SHADER: if (spec != SH_CSS_SHADERS_SPEC) { // Set up gl_FragData. The array size. - TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, false, true); + TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true); fragData.setArraySize(resources.MaxDrawBuffers); - symbolTable.insert(*new TVariable(NewPoolTString("gl_FragData"), fragData)); + symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData"), fragData)); } break; default: break; @@ -561,4 +756,6 @@ void InitExtensionBehavior(const ShBuiltInResources& resources, extBehavior["GL_EXT_draw_buffers"] = EBhUndefined; if (resources.EXT_frag_depth) extBehavior["GL_EXT_frag_depth"] = EBhUndefined; + if (resources.EXT_shader_texture_lod) + extBehavior["GL_EXT_shader_texture_lod"] = EBhUndefined; } diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.h b/src/3rdparty/angle/src/compiler/translator/Initialize.h index b5642869aa..cc1862c90e 100644 --- a/src/3rdparty/angle/src/compiler/translator/Initialize.h +++ b/src/3rdparty/angle/src/compiler/translator/Initialize.h @@ -8,12 +8,12 @@ #define _INITIALIZE_INCLUDED_ #include "compiler/translator/Common.h" -#include "compiler/translator/ShHandle.h" +#include "compiler/translator/Compiler.h" #include "compiler/translator/SymbolTable.h" -void InsertBuiltInFunctions(ShShaderType type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table); +void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources &resources, TSymbolTable &table); -void IdentifyBuiltIns(ShShaderType type, ShShaderSpec spec, +void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec, const ShBuiltInResources& resources, TSymbolTable& symbolTable); diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp index 43f81784d0..c98430662a 100644 --- a/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp +++ b/src/3rdparty/angle/src/compiler/translator/InitializeDll.cpp @@ -5,10 +5,12 @@ // #include "compiler/translator/InitializeDll.h" - #include "compiler/translator/InitializeGlobals.h" #include "compiler/translator/InitializeParseContext.h" -#include "compiler/translator/osinclude.h" + +#include "common/platform.h" + +#include bool InitProcess() { diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.cpp index b4defae569..c35cedb348 100644 --- a/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.cpp +++ b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.cpp @@ -6,35 +6,37 @@ #include "compiler/translator/InitializeParseContext.h" -#include "compiler/translator/osinclude.h" +#include "common/tls.h" -OS_TLSIndex GlobalParseContextIndex = OS_INVALID_TLS_INDEX; +#include + +TLSIndex GlobalParseContextIndex = TLS_INVALID_INDEX; bool InitializeParseContextIndex() { - assert(GlobalParseContextIndex == OS_INVALID_TLS_INDEX); + assert(GlobalParseContextIndex == TLS_INVALID_INDEX); - GlobalParseContextIndex = OS_AllocTLSIndex(); - return GlobalParseContextIndex != OS_INVALID_TLS_INDEX; + GlobalParseContextIndex = CreateTLSIndex(); + return GlobalParseContextIndex != TLS_INVALID_INDEX; } void FreeParseContextIndex() { - assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); + assert(GlobalParseContextIndex != TLS_INVALID_INDEX); - OS_FreeTLSIndex(GlobalParseContextIndex); - GlobalParseContextIndex = OS_INVALID_TLS_INDEX; + DestroyTLSIndex(GlobalParseContextIndex); + GlobalParseContextIndex = TLS_INVALID_INDEX; } void SetGlobalParseContext(TParseContext* context) { - assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); - OS_SetTLSValue(GlobalParseContextIndex, context); + assert(GlobalParseContextIndex != TLS_INVALID_INDEX); + SetTLSValue(GlobalParseContextIndex, context); } TParseContext* GetGlobalParseContext() { - assert(GlobalParseContextIndex != OS_INVALID_TLS_INDEX); - return static_cast(OS_GetTLSValue(GlobalParseContextIndex)); + assert(GlobalParseContextIndex != TLS_INVALID_INDEX); + return static_cast(GetTLSValue(GlobalParseContextIndex)); } diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp index 115c561c77..0e3e2ebe55 100644 --- a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp +++ b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.cpp @@ -10,7 +10,7 @@ namespace { -TIntermConstantUnion* constructFloatConstUnionNode(const TType& type) +TIntermConstantUnion *constructFloatConstUnionNode(const TType &type) { TType myType = type; unsigned char size = myType.getNominalSize(); @@ -26,7 +26,7 @@ TIntermConstantUnion* constructFloatConstUnionNode(const TType& type) return node; } -TIntermConstantUnion* constructIndexNode(int index) +TIntermConstantUnion *constructIndexNode(int index) { ConstantUnion *u = new ConstantUnion[1]; u[0].setIConst(index); @@ -38,7 +38,7 @@ TIntermConstantUnion* constructIndexNode(int index) } // namespace anonymous -bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate* node) +bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate *node) { bool visitChildren = !mCodeInserted; switch (node->getOp()) @@ -51,17 +51,17 @@ bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate* node) ASSERT(visit == PreVisit); if (node->getName() == "main(") { - TIntermSequence &sequence = node->getSequence(); - ASSERT((sequence.size() == 1) || (sequence.size() == 2)); + TIntermSequence *sequence = node->getSequence(); + ASSERT((sequence->size() == 1) || (sequence->size() == 2)); TIntermAggregate *body = NULL; - if (sequence.size() == 1) + if (sequence->size() == 1) { body = new TIntermAggregate(EOpSequence); - sequence.push_back(body); + sequence->push_back(body); } else { - body = sequence[1]->getAsAggregate(); + body = (*sequence)[1]->getAsAggregate(); } ASSERT(body); insertInitCode(body->getSequence()); @@ -76,18 +76,18 @@ bool InitializeVariables::visitAggregate(Visit visit, TIntermAggregate* node) return visitChildren; } -void InitializeVariables::insertInitCode(TIntermSequence& sequence) +void InitializeVariables::insertInitCode(TIntermSequence *sequence) { for (size_t ii = 0; ii < mVariables.size(); ++ii) { - const InitVariableInfo& varInfo = mVariables[ii]; + const InitVariableInfo &varInfo = mVariables[ii]; if (varInfo.type.isArray()) { for (int index = varInfo.type.getArraySize() - 1; index >= 0; --index) { TIntermBinary *assign = new TIntermBinary(EOpAssign); - sequence.insert(sequence.begin(), assign); + sequence->insert(sequence->begin(), assign); TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect); TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type); @@ -104,7 +104,7 @@ void InitializeVariables::insertInitCode(TIntermSequence& sequence) else { TIntermBinary *assign = new TIntermBinary(EOpAssign); - sequence.insert(sequence.begin(), assign); + sequence->insert(sequence->begin(), assign); TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type); assign->setLeft(symbol); TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type); diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h index 1cd6d7e1b5..81ab9fe90f 100644 --- a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h +++ b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h @@ -17,7 +17,7 @@ class InitializeVariables : public TIntermTraverser TString name; TType type; - InitVariableInfo(const TString& _name, const TType& _type) + InitVariableInfo(const TString &_name, const TType &_type) : name(_name), type(_type) { @@ -25,23 +25,23 @@ class InitializeVariables : public TIntermTraverser }; typedef TVector InitVariableInfoList; - InitializeVariables(const InitVariableInfoList& vars) + InitializeVariables(const InitVariableInfoList &vars) : mCodeInserted(false), mVariables(vars) { } protected: - virtual bool visitBinary(Visit visit, TIntermBinary* node) { return false; } - virtual bool visitUnary(Visit visit, TIntermUnary* node) { return false; } - virtual bool visitSelection(Visit visit, TIntermSelection* node) { return false; } - virtual bool visitLoop(Visit visit, TIntermLoop* node) { return false; } - virtual bool visitBranch(Visit visit, TIntermBranch* node) { return false; } + virtual bool visitBinary(Visit, TIntermBinary *node) { return false; } + virtual bool visitUnary(Visit, TIntermUnary *node) { return false; } + virtual bool visitSelection(Visit, TIntermSelection *node) { return false; } + virtual bool visitLoop(Visit, TIntermLoop *node) { return false; } + virtual bool visitBranch(Visit, TIntermBranch *node) { return false; } virtual bool visitAggregate(Visit visit, TIntermAggregate* node); private: - void insertInitCode(TIntermSequence& sequence); + void insertInitCode(TIntermSequence *sequence); InitVariableInfoList mVariables; bool mCodeInserted; diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp index 554b83409a..48d2013cc5 100644 --- a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp +++ b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp @@ -45,7 +45,7 @@ void TIntermBinary::traverse(TIntermTraverser *it) // if (it->preVisit) visit = it->visitBinary(PreVisit, this); - + // // Visit the children, in the right order. // @@ -53,27 +53,27 @@ void TIntermBinary::traverse(TIntermTraverser *it) { it->incrementDepth(this); - if (it->rightToLeft) + if (it->rightToLeft) { - if (right) - right->traverse(it); - + if (mRight) + mRight->traverse(it); + if (it->inVisit) visit = it->visitBinary(InVisit, this); - if (visit && left) - left->traverse(it); + if (visit && mLeft) + mLeft->traverse(it); } else { - if (left) - left->traverse(it); - + if (mLeft) + mLeft->traverse(it); + if (it->inVisit) visit = it->visitBinary(InVisit, this); - if (visit && right) - right->traverse(it); + if (visit && mRight) + mRight->traverse(it); } it->decrementDepth(); @@ -99,10 +99,10 @@ void TIntermUnary::traverse(TIntermTraverser *it) if (visit) { it->incrementDepth(this); - operand->traverse(it); + mOperand->traverse(it); it->decrementDepth(); } - + if (visit && it->postVisit) it->visitUnary(PostVisit, this); } @@ -113,41 +113,43 @@ void TIntermUnary::traverse(TIntermTraverser *it) void TIntermAggregate::traverse(TIntermTraverser *it) { bool visit = true; - + if (it->preVisit) visit = it->visitAggregate(PreVisit, this); - + if (visit) { it->incrementDepth(this); if (it->rightToLeft) { - for (TIntermSequence::reverse_iterator sit = sequence.rbegin(); sit != sequence.rend(); sit++) + for (TIntermSequence::reverse_iterator sit = mSequence.rbegin(); + sit != mSequence.rend(); sit++) { (*sit)->traverse(it); if (visit && it->inVisit) { - if (*sit != sequence.front()) + if (*sit != mSequence.front()) visit = it->visitAggregate(InVisit, this); } } } else { - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) + for (TIntermSequence::iterator sit = mSequence.begin(); + sit != mSequence.end(); sit++) { (*sit)->traverse(it); if (visit && it->inVisit) { - if (*sit != sequence.back()) + if (*sit != mSequence.back()) visit = it->visitAggregate(InVisit, this); } } } - + it->decrementDepth(); } @@ -164,21 +166,25 @@ void TIntermSelection::traverse(TIntermTraverser *it) if (it->preVisit) visit = it->visitSelection(PreVisit, this); - - if (visit) { + + if (visit) + { it->incrementDepth(this); - if (it->rightToLeft) { - if (falseBlock) - falseBlock->traverse(it); - if (trueBlock) - trueBlock->traverse(it); - condition->traverse(it); - } else { - condition->traverse(it); - if (trueBlock) - trueBlock->traverse(it); - if (falseBlock) - falseBlock->traverse(it); + if (it->rightToLeft) + { + if (mFalseBlock) + mFalseBlock->traverse(it); + if (mTrueBlock) + mTrueBlock->traverse(it); + mCondition->traverse(it); + } + else + { + mCondition->traverse(it); + if (mTrueBlock) + mTrueBlock->traverse(it); + if (mFalseBlock) + mFalseBlock->traverse(it); } it->decrementDepth(); } @@ -196,38 +202,38 @@ void TIntermLoop::traverse(TIntermTraverser *it) if (it->preVisit) visit = it->visitLoop(PreVisit, this); - + if (visit) { it->incrementDepth(this); if (it->rightToLeft) { - if (expr) - expr->traverse(it); + if (mExpr) + mExpr->traverse(it); - if (body) - body->traverse(it); + if (mBody) + mBody->traverse(it); - if (cond) - cond->traverse(it); + if (mCond) + mCond->traverse(it); - if (init) - init->traverse(it); + if (mInit) + mInit->traverse(it); } else { - if (init) - init->traverse(it); + if (mInit) + mInit->traverse(it); - if (cond) - cond->traverse(it); + if (mCond) + mCond->traverse(it); - if (body) - body->traverse(it); + if (mBody) + mBody->traverse(it); - if (expr) - expr->traverse(it); + if (mExpr) + mExpr->traverse(it); } it->decrementDepth(); @@ -246,10 +252,10 @@ void TIntermBranch::traverse(TIntermTraverser *it) if (it->preVisit) visit = it->visitBranch(PreVisit, this); - - if (visit && expression) { + + if (visit && mExpression) { it->incrementDepth(this); - expression->traverse(it); + mExpression->traverse(it); it->decrementDepth(); } @@ -257,3 +263,7 @@ void TIntermBranch::traverse(TIntermTraverser *it) it->visitBranch(PostVisit, this); } +void TIntermRaw::traverse(TIntermTraverser *it) +{ + it->visitRaw(this); +} diff --git a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp index 777cab5458..fa0c9f7748 100644 --- a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp +++ b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2013 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. // @@ -16,110 +16,118 @@ #include "compiler/translator/localintermediate.h" #include "compiler/translator/QualifierAlive.h" #include "compiler/translator/RemoveTree.h" +#include "compiler/translator/SymbolTable.h" -bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray); +namespace +{ -static TPrecision GetHigherPrecision(TPrecision left, TPrecision right) +TPrecision GetHigherPrecision(TPrecision left, TPrecision right) { return left > right ? left : right; } -const char* getOperatorString(TOperator op) +bool ValidateMultiplication(TOperator op, const TType &left, const TType &right) { - switch (op) { - case EOpInitialize: return "="; - case EOpAssign: return "="; - case EOpAddAssign: return "+="; - case EOpSubAssign: return "-="; - case EOpDivAssign: return "/="; - - // Fall-through. - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: return "*="; - - // Fall-through. - case EOpIndexDirect: - case EOpIndexIndirect: return "[]"; - - case EOpIndexDirectStruct: return "."; - case EOpVectorSwizzle: return "."; - case EOpAdd: return "+"; - case EOpSub: return "-"; - case EOpMul: return "*"; - case EOpDiv: return "/"; - case EOpMod: UNIMPLEMENTED(); break; - case EOpEqual: return "=="; - case EOpNotEqual: return "!="; - case EOpLessThan: return "<"; - case EOpGreaterThan: return ">"; - case EOpLessThanEqual: return "<="; - case EOpGreaterThanEqual: return ">="; - - // Fall-through. + 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 EOpMatrixTimesMatrix: return "*"; - - case EOpLogicalOr: return "||"; - case EOpLogicalXor: return "^^"; - case EOpLogicalAnd: return "&&"; - case EOpNegative: return "-"; - case EOpVectorLogicalNot: return "not"; - case EOpLogicalNot: return "!"; - case EOpPostIncrement: return "++"; - case EOpPostDecrement: return "--"; - case EOpPreIncrement: return "++"; - case EOpPreDecrement: return "--"; - - // Fall-through. - case EOpConvIntToBool: - case EOpConvFloatToBool: return "bool"; - - // Fall-through. - case EOpConvBoolToFloat: - case EOpConvIntToFloat: return "float"; - - // Fall-through. - case EOpConvFloatToInt: - case EOpConvBoolToInt: return "int"; - - case EOpRadians: return "radians"; - case EOpDegrees: return "degrees"; - case EOpSin: return "sin"; - case EOpCos: return "cos"; - case EOpTan: return "tan"; - case EOpAsin: return "asin"; - case EOpAcos: return "acos"; - case EOpAtan: return "atan"; - case EOpExp: return "exp"; - case EOpLog: return "log"; - case EOpExp2: return "exp2"; - case EOpLog2: return "log2"; - case EOpSqrt: return "sqrt"; - case EOpInverseSqrt: return "inversesqrt"; - case EOpAbs: return "abs"; - case EOpSign: return "sign"; - case EOpFloor: return "floor"; - case EOpCeil: return "ceil"; - case EOpFract: return "fract"; - case EOpLength: return "length"; - case EOpNormalize: return "normalize"; - case EOpDFdx: return "dFdx"; - case EOpDFdy: return "dFdy"; - case EOpFwidth: return "fwidth"; - case EOpAny: return "any"; - case EOpAll: return "all"; - - default: break; + 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 ""; + 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. @@ -133,9 +141,10 @@ const char* getOperatorString(TOperator op) // // Returns the added node. // -TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType& type, const TSourceLoc& line) +TIntermSymbol *TIntermediate::addSymbol( + int id, const TString &name, const TType &type, const TSourceLoc &line) { - TIntermSymbol* node = new TIntermSymbol(id, name, type); + TIntermSymbol *node = new TIntermSymbol(id, name, type); node->setLine(line); return node; @@ -146,77 +155,71 @@ TIntermSymbol* TIntermediate::addSymbol(int id, const TString& name, const TType // // Returns the added node. // -TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line, TSymbolTable& symbolTable) +TIntermTyped *TIntermediate::addBinaryMath( + TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line) { - switch (op) { - case EOpEqual: - case EOpNotEqual: - if (left->isArray()) - return 0; - break; - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) { - return 0; - } - break; - case EOpLogicalOr: - case EOpLogicalXor: - case EOpLogicalAnd: - if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) { - return 0; - } - break; - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpMul: - if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) - return 0; - default: break; + switch (op) + { + case EOpEqual: + case EOpNotEqual: + if (left->isArray()) + return NULL; + break; + case EOpLessThan: + case EOpGreaterThan: + case EOpLessThanEqual: + case EOpGreaterThanEqual: + if (left->isMatrix() || left->isArray() || left->isVector() || + left->getBasicType() == EbtStruct) + { + return NULL; + } + break; + case EOpLogicalOr: + case EOpLogicalXor: + case EOpLogicalAnd: + if (left->getBasicType() != EbtBool || + left->isMatrix() || left->isArray() || left->isVector()) + { + return NULL; + } + break; + case EOpAdd: + case EOpSub: + case EOpDiv: + case EOpMul: + if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) + return NULL; + default: + break; } - // - // First try converting the children to compatible types. - // - if (left->getType().getStruct() && right->getType().getStruct()) { - if (left->getType() != right->getType()) - return 0; - } else { - TIntermTyped* child = addConversion(op, left->getType(), right); - if (child) - right = child; - else { - child = addConversion(op, right->getType(), left); - if (child) - left = child; - else - return 0; - } + if (left->getBasicType() != right->getBasicType()) + { + return NULL; } // // Need a new node holding things together then. Make // one and promote it to the right type. // - TIntermBinary* node = new TIntermBinary(op); + TIntermBinary *node = new TIntermBinary(op); node->setLine(line); node->setLeft(left); node->setRight(right); - if (!node->promote(infoSink)) - return 0; + if (!node->promote(mInfoSink)) + return NULL; // // See if we can fold constants. // - TIntermTyped* typedReturnNode = 0; TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion(); TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion(); - if (leftTempConstant && rightTempConstant) { - typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink); + if (leftTempConstant && rightTempConstant) + { + TIntermTyped *typedReturnNode = + leftTempConstant->fold(node->getOp(), rightTempConstant, mInfoSink); if (typedReturnNode) return typedReturnNode; @@ -230,23 +233,24 @@ TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIn // // Returns the added node. // -TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) +TIntermTyped *TIntermediate::addAssign( + TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line) { - // - // Like adding binary math, except the conversion can only go - // from right to left. - // - TIntermBinary* node = new TIntermBinary(op); - node->setLine(line); + if (left->getType().getStruct() || right->getType().getStruct()) + { + if (left->getType() != right->getType()) + { + return NULL; + } + } - TIntermTyped* child = addConversion(op, left->getType(), right); - if (child == 0) - return 0; + TIntermBinary *node = new TIntermBinary(op); + node->setLine(line); node->setLeft(left); - node->setRight(child); - if (! node->promote(infoSink)) - return 0; + node->setRight(right); + if (!node->promote(mInfoSink)) + return NULL; return node; } @@ -258,9 +262,10 @@ TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TInterm // Returns the added node. // The caller should set the type of the returned node. // -TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc& line) +TIntermTyped *TIntermediate::addIndex( + TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &line) { - TIntermBinary* node = new TIntermBinary(op); + TIntermBinary *node = new TIntermBinary(op); node->setLine(line); node->setLeft(base); node->setRight(index); @@ -275,65 +280,43 @@ TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermT // // Returns the added node. // -TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, const TSourceLoc& line, TSymbolTable& symbolTable) +TIntermTyped *TIntermediate::addUnaryMath( + TOperator op, TIntermNode *childNode, const TSourceLoc &line) { - TIntermUnary* node; - TIntermTyped* child = childNode->getAsTyped(); - - if (child == 0) { - infoSink.info.message(EPrefixInternalError, line, "Bad type in AddUnaryMath"); - return 0; - } - - switch (op) { - case EOpLogicalNot: - if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) { - return 0; - } - break; - - case EOpPostIncrement: - case EOpPreIncrement: - case EOpPostDecrement: - case EOpPreDecrement: - case EOpNegative: - if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) - return 0; - default: break; - } - - // - // Do we need to promote the operand? - // - // Note: Implicit promotions were removed from the language. - // - TBasicType newType = EbtVoid; - switch (op) { - case EOpConstructInt: newType = EbtInt; break; - case EOpConstructBool: newType = EbtBool; break; - case EOpConstructFloat: newType = EbtFloat; break; - default: break; - } + TIntermUnary *node; + TIntermTyped *child = childNode->getAsTyped(); - if (newType != EbtVoid) { - child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary, - child->getNominalSize(), - child->isMatrix(), - child->isArray()), - child); - if (child == 0) - return 0; + if (child == NULL) + { + mInfoSink.info.message(EPrefixInternalError, line, + "Bad type in AddUnaryMath"); + return NULL; } - // - // For constructors, we are now done, it's all in the conversion. - // - switch (op) { - case EOpConstructInt: - case EOpConstructBool: - case EOpConstructFloat: - return child; - default: break; + switch (op) + { + case EOpLogicalNot: + if (child->getType().getBasicType() != EbtBool || + child->getType().isMatrix() || + child->getType().isArray() || + child->getType().isVector()) + { + return NULL; + } + break; + + case EOpPostIncrement: + case EOpPreIncrement: + case EOpPostDecrement: + case EOpPreDecrement: + case EOpNegative: + if (child->getType().getBasicType() == EbtStruct || + child->getType().isArray()) + { + return NULL; + } + default: + break; } TIntermConstantUnion *childTempConstant = 0; @@ -347,11 +330,12 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, node->setLine(line); node->setOperand(child); - if (! node->promote(infoSink)) + if (!node->promote(mInfoSink)) return 0; - if (childTempConstant) { - TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink); + if (childTempConstant) + { + TIntermTyped *newChild = childTempConstant->fold(op, 0, mInfoSink); if (newChild) return newChild; @@ -370,24 +354,30 @@ TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, // Returns an aggregate node, which could be the one passed in if // it was already an aggregate but no operator was set. // -TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperator op, const TSourceLoc& line) +TIntermAggregate *TIntermediate::setAggregateOperator( + TIntermNode *node, TOperator op, const TSourceLoc &line) { - TIntermAggregate* aggNode; + TIntermAggregate *aggNode; // // Make sure we have an aggregate. If not turn it into one. // - if (node) { + if (node) + { aggNode = node->getAsAggregate(); - if (aggNode == 0 || aggNode->getOp() != EOpNull) { + if (aggNode == NULL || aggNode->getOp() != EOpNull) + { // // Make an aggregate containing this node. // aggNode = new TIntermAggregate(); - aggNode->getSequence().push_back(node); + aggNode->getSequence()->push_back(node); } - } else + } + else + { aggNode = new TIntermAggregate(); + } // // Set the operator. @@ -398,126 +388,6 @@ TIntermAggregate* TIntermediate::setAggregateOperator(TIntermNode* node, TOperat return aggNode; } -// -// Convert one type to another. -// -// Returns the node representing the conversion, which could be the same -// node passed in if no conversion was needed. -// -// Return 0 if a conversion can't be done. -// -TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TIntermTyped* node) -{ - // - // Does the base type allow operation? - // - switch (node->getBasicType()) { - case EbtVoid: - case EbtSampler2D: - case EbtSamplerCube: - return 0; - default: break; - } - - // - // Otherwise, if types are identical, no problem - // - if (type == node->getType()) - return node; - - // - // If one's a structure, then no conversions. - // - if (type.getStruct() || node->getType().getStruct()) - return 0; - - // - // If one's an array, then no conversions. - // - if (type.isArray() || node->getType().isArray()) - return 0; - - TBasicType promoteTo; - - switch (op) { - // - // Explicit conversions - // - case EOpConstructBool: - promoteTo = EbtBool; - break; - case EOpConstructFloat: - promoteTo = EbtFloat; - break; - case EOpConstructInt: - promoteTo = EbtInt; - break; - default: - // - // implicit conversions were removed from the language. - // - if (type.getBasicType() != node->getType().getBasicType()) - return 0; - // - // Size and structure could still differ, but that's - // handled by operator promotion. - // - return node; - } - - if (node->getAsConstantUnion()) { - - return (promoteConstantUnion(promoteTo, node->getAsConstantUnion())); - } else { - - // - // Add a new newNode for the conversion. - // - TIntermUnary* newNode = 0; - - TOperator newOp = EOpNull; - switch (promoteTo) { - case EbtFloat: - switch (node->getBasicType()) { - case EbtInt: newOp = EOpConvIntToFloat; break; - case EbtBool: newOp = EOpConvBoolToFloat; break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); - return 0; - } - break; - case EbtBool: - switch (node->getBasicType()) { - case EbtInt: newOp = EOpConvIntToBool; break; - case EbtFloat: newOp = EOpConvFloatToBool; break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); - return 0; - } - break; - case EbtInt: - switch (node->getBasicType()) { - case EbtBool: newOp = EOpConvBoolToInt; break; - case EbtFloat: newOp = EOpConvFloatToInt; break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion node"); - return 0; - } - break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Bad promotion type"); - return 0; - } - - TType type(promoteTo, node->getPrecision(), EvqTemporary, node->getNominalSize(), node->isMatrix(), node->isArray()); - newNode = new TIntermUnary(newOp, type); - newNode->setLine(node->getLine()); - newNode->setOperand(node); - - return newNode; - } -} - // // Safe way to combine two nodes into an aggregate. Works with null pointers, // a node that's not a aggregate yet, etc. @@ -525,22 +395,24 @@ TIntermTyped* TIntermediate::addConversion(TOperator op, const TType& type, TInt // Returns the resulting aggregate, unless 0 was passed in for // both existing nodes. // -TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc& line) +TIntermAggregate *TIntermediate::growAggregate( + TIntermNode *left, TIntermNode *right, const TSourceLoc &line) { - if (left == 0 && right == 0) - return 0; + if (left == NULL && right == NULL) + return NULL; - TIntermAggregate* aggNode = 0; + TIntermAggregate *aggNode = NULL; if (left) aggNode = left->getAsAggregate(); - if (!aggNode || aggNode->getOp() != EOpNull) { + if (!aggNode || aggNode->getOp() != EOpNull) + { aggNode = new TIntermAggregate; if (left) - aggNode->getSequence().push_back(left); + aggNode->getSequence()->push_back(left); } if (right) - aggNode->getSequence().push_back(right); + aggNode->getSequence()->push_back(right); aggNode->setLine(line); @@ -550,15 +422,17 @@ TIntermAggregate* TIntermediate::growAggregate(TIntermNode* left, TIntermNode* r // // Turn an existing node into an aggregate. // -// Returns an aggregate, unless 0 was passed in for the existing node. +// Returns an aggregate, unless NULL was passed in for the existing node. // -TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceLoc& line) +TIntermAggregate *TIntermediate::makeAggregate( + TIntermNode *node, const TSourceLoc &line) { - if (node == 0) - return 0; + if (node == NULL) + return NULL; + + TIntermAggregate *aggNode = new TIntermAggregate; + aggNode->getSequence()->push_back(node); - TIntermAggregate* aggNode = new TIntermAggregate; - aggNode->getSequence().push_back(node); aggNode->setLine(line); return aggNode; @@ -571,32 +445,45 @@ TIntermAggregate* TIntermediate::makeAggregate(TIntermNode* node, const TSourceL // // Returns the selection node created. // -TIntermNode* TIntermediate::addSelection(TIntermTyped* cond, TIntermNodePair nodePair, const TSourceLoc& line) +TIntermNode *TIntermediate::addSelection( + TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line) { // // For compile time constant selections, prune the code and // test now. // - if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) { + if (cond->getAsTyped() && cond->getAsTyped()->getAsConstantUnion()) + { if (cond->getAsConstantUnion()->getBConst(0) == true) - return nodePair.node1 ? setAggregateOperator(nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL; + { + return nodePair.node1 ? setAggregateOperator( + nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL; + } else - return nodePair.node2 ? setAggregateOperator(nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL; + { + return nodePair.node2 ? setAggregateOperator( + nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL; + } } - TIntermSelection* node = new TIntermSelection(cond, nodePair.node1, nodePair.node2); + TIntermSelection *node = new TIntermSelection( + cond, nodePair.node1, nodePair.node2); node->setLine(line); return node; } - -TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) +TIntermTyped *TIntermediate::addComma( + TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line) { - if (left->getType().getQualifier() == EvqConst && right->getType().getQualifier() == EvqConst) { + if (left->getType().getQualifier() == EvqConst && + right->getType().getQualifier() == EvqConst) + { return right; - } else { + } + else + { TIntermTyped *commaAggregate = growAggregate(left, right, line); commaAggregate->getAsAggregate()->setOp(EOpComma); commaAggregate->setType(right->getType()); @@ -612,27 +499,24 @@ TIntermTyped* TIntermediate::addComma(TIntermTyped* left, TIntermTyped* right, c // // Returns the selection node created, or 0 if one could not be. // -TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc& line) +TIntermTyped *TIntermediate::addSelection( + TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, + const TSourceLoc &line) { - // - // Get compatible types. - // - TIntermTyped* child = addConversion(EOpSequence, trueBlock->getType(), falseBlock); - if (child) - falseBlock = child; - else { - child = addConversion(EOpSequence, falseBlock->getType(), trueBlock); - if (child) - trueBlock = child; - else - return 0; + if (!cond || !trueBlock || !falseBlock || + trueBlock->getType() != falseBlock->getType()) + { + return NULL; } // // See if all the operands are constant, then fold it otherwise not. // - if (cond->getAsConstantUnion() && trueBlock->getAsConstantUnion() && falseBlock->getAsConstantUnion()) { + if (cond->getAsConstantUnion() && + trueBlock->getAsConstantUnion() && + falseBlock->getAsConstantUnion()) + { if (cond->getAsConstantUnion()->getBConst(0)) return trueBlock; else @@ -642,7 +526,8 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true // // Make a selection node. // - TIntermSelection* node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType()); + TIntermSelection *node = new TIntermSelection( + cond, trueBlock, falseBlock, trueBlock->getType()); node->getTypePointer()->setQualifier(EvqTemporary); node->setLine(line); @@ -655,29 +540,33 @@ TIntermTyped* TIntermediate::addSelection(TIntermTyped* cond, TIntermTyped* true // Returns the constant union node created. // -TIntermConstantUnion* TIntermediate::addConstantUnion(ConstantUnion* unionArrayPointer, const TType& t, const TSourceLoc& line) +TIntermConstantUnion *TIntermediate::addConstantUnion( + ConstantUnion *unionArrayPointer, const TType &t, const TSourceLoc &line) { - TIntermConstantUnion* node = new TIntermConstantUnion(unionArrayPointer, t); + TIntermConstantUnion *node = new TIntermConstantUnion(unionArrayPointer, t); node->setLine(line); return node; } -TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& line) +TIntermTyped *TIntermediate::addSwizzle( + TVectorFields &fields, const TSourceLoc &line) { - TIntermAggregate* node = new TIntermAggregate(EOpSequence); + TIntermAggregate *node = new TIntermAggregate(EOpSequence); node->setLine(line); - TIntermConstantUnion* constIntNode; - TIntermSequence &sequenceVector = node->getSequence(); - ConstantUnion* unionArray; + TIntermConstantUnion *constIntNode; + TIntermSequence *sequenceVector = node->getSequence(); + ConstantUnion *unionArray; - for (int i = 0; i < fields.num; i++) { + for (int i = 0; i < fields.num; i++) + { unionArray = new ConstantUnion[1]; unionArray->setIConst(fields.offsets[i]); - constIntNode = addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), line); - sequenceVector.push_back(constIntNode); + constIntNode = addConstantUnion( + unionArray, TType(EbtInt, EbpUndefined, EvqConst), line); + sequenceVector->push_back(constIntNode); } return node; @@ -686,9 +575,11 @@ TIntermTyped* TIntermediate::addSwizzle(TVectorFields& fields, const TSourceLoc& // // Create loop nodes. // -TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTyped* cond, TIntermTyped* expr, TIntermNode* body, const TSourceLoc& line) +TIntermNode *TIntermediate::addLoop( + TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr, + TIntermNode *body, const TSourceLoc &line) { - TIntermNode* node = new TIntermLoop(type, init, cond, expr, body); + TIntermNode *node = new TIntermLoop(type, init, cond, expr, body); node->setLine(line); return node; @@ -697,14 +588,16 @@ TIntermNode* TIntermediate::addLoop(TLoopType type, TIntermNode* init, TIntermTy // // Add branches. // -TIntermBranch* TIntermediate::addBranch(TOperator branchOp, const TSourceLoc& line) +TIntermBranch* TIntermediate::addBranch( + TOperator branchOp, const TSourceLoc &line) { return addBranch(branchOp, 0, line); } -TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expression, const TSourceLoc& line) +TIntermBranch* TIntermediate::addBranch( + TOperator branchOp, TIntermTyped *expression, const TSourceLoc &line) { - TIntermBranch* node = new TIntermBranch(branchOp, expression); + TIntermBranch *node = new TIntermBranch(branchOp, expression); node->setLine(line); return node; @@ -714,15 +607,15 @@ TIntermBranch* TIntermediate::addBranch(TOperator branchOp, TIntermTyped* expres // This is to be executed once the final root is put on top by the parsing // process. // -bool TIntermediate::postProcess(TIntermNode* root) +bool TIntermediate::postProcess(TIntermNode *root) { - if (root == 0) + if (root == NULL) return true; // // First, finish off the top level sequence, if any // - TIntermAggregate* aggRoot = root->getAsAggregate(); + TIntermAggregate *aggRoot = root->getAsAggregate(); if (aggRoot && aggRoot->getOp() == EOpNull) aggRoot->setOp(EOpSequence); @@ -732,7 +625,7 @@ bool TIntermediate::postProcess(TIntermNode* root) // // This deletes the tree. // -void TIntermediate::remove(TIntermNode* root) +void TIntermediate::remove(TIntermNode *root) { if (root) RemoveAllTreeNodes(root); @@ -753,76 +646,149 @@ void TIntermediate::remove(TIntermNode* root) bool TIntermLoop::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { - REPLACE_IF_IS(init, TIntermNode, original, replacement); - REPLACE_IF_IS(cond, TIntermTyped, original, replacement); - REPLACE_IF_IS(expr, TIntermTyped, original, replacement); - REPLACE_IF_IS(body, TIntermNode, original, replacement); + 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(expression, TIntermTyped, original, 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(left, TIntermTyped, original, replacement); - REPLACE_IF_IS(right, TIntermTyped, original, 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(operand, TIntermTyped, original, 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 < sequence.size(); ++ii) + for (size_t ii = 0; ii < mSequence.size(); ++ii) { - REPLACE_IF_IS(sequence[ii], TIntermNode, original, replacement); + 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(condition, TIntermTyped, original, replacement); - REPLACE_IF_IS(trueBlock, TIntermNode, original, replacement); - REPLACE_IF_IS(falseBlock, TIntermNode, original, 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 (op) { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - case EOpAssign: - case EOpAddAssign: - case EOpSubAssign: - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - case EOpDivAssign: - return true; - default: - return false; + 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; } } @@ -831,26 +797,31 @@ bool TIntermOperator::isAssignment() const // bool TIntermOperator::isConstructor() const { - switch (op) { - case EOpConstructVec2: - case EOpConstructVec3: - case EOpConstructVec4: - case EOpConstructMat2: - case EOpConstructMat3: - case EOpConstructMat4: - case EOpConstructFloat: - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructInt: - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructBool: - case EOpConstructStruct: - return true; - default: - return false; + 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; } } @@ -860,35 +831,36 @@ bool TIntermOperator::isConstructor() const // // Returns false in nothing makes sense. // -bool TIntermUnary::promote(TInfoSink&) +bool TIntermUnary::promote(TInfoSink &) { - switch (op) { - case EOpLogicalNot: - if (operand->getBasicType() != EbtBool) - return false; - break; - case EOpNegative: - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - if (operand->getBasicType() == EbtBool) - return false; - break; + 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; + // operators for built-ins are already type checked against their prototype + case EOpAny: + case EOpAll: + case EOpVectorLogicalNot: + return true; - default: - if (operand->getBasicType() != EbtFloat) - return false; + default: + if (mOperand->getBasicType() != EbtFloat) + return false; } - setType(operand->getType()); - type.setQualifier(EvqTemporary); + setType(mOperand->getType()); + mType.setQualifier(EvqTemporary); return true; } @@ -899,221 +871,260 @@ bool TIntermUnary::promote(TInfoSink&) // // Returns false if operator can't work on operands. // -bool TIntermBinary::promote(TInfoSink& infoSink) +bool TIntermBinary::promote(TInfoSink &infoSink) { // This function only handles scalars, vectors, and matrices. - if (left->isArray() || right->isArray()) { - infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operation for arrays"); + 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 (left->getBasicType() != right->getBasicType()) + 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(left->getType()); + setType(mLeft->getType()); // The result gets promoted to the highest precision. - TPrecision higherPrecision = GetHigherPrecision(left->getPrecision(), right->getPrecision()); + TPrecision higherPrecision = GetHigherPrecision( + mLeft->getPrecision(), mRight->getPrecision()); getTypePointer()->setPrecision(higherPrecision); // Binary operations results in temporary variables unless both // operands are const. - if (left->getQualifier() != EvqConst || right->getQualifier() != EvqConst) { + if (mLeft->getQualifier() != EvqConst || mRight->getQualifier() != EvqConst) + { getTypePointer()->setQualifier(EvqTemporary); } - int size = std::max(left->getNominalSize(), right->getNominalSize()); + const int nominalSize = + std::max(mLeft->getNominalSize(), mRight->getNominalSize()); // - // All scalars. Code after this test assumes this case is removed! + // All scalars or structs. Code after this test assumes this case is removed! // - if (size == 1) { - switch (op) { - // - // Promote to conditional - // - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - setType(TType(EbtBool, EbpUndefined)); - break; + 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 (left->getBasicType() != EbtBool || right->getBasicType() != EbtBool) - return false; - 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; + default: + break; } return true; } // If we reach here, at least one of the operands is vector or matrix. // The other operand could be a scalar, vector, or matrix. - // Are the sizes compatible? - // - if (left->getNominalSize() != right->getNominalSize()) { - // If the nominal size of operands do not match: - // One of them must be scalar. - if (left->getNominalSize() != 1 && right->getNominalSize() != 1) - return false; - // Operator cannot be of type pure assignment. - if (op == EOpAssign || op == EOpInitialize) - return false; - } - - // // Can these two operands be combined? // - TBasicType basicType = left->getBasicType(); - switch (op) { - case EOpMul: - if (!left->isMatrix() && right->isMatrix()) { - if (left->isVector()) - op = EOpVectorTimesMatrix; - else { - op = EOpMatrixTimesScalar; - setType(TType(basicType, higherPrecision, EvqTemporary, size, true)); - } - } else if (left->isMatrix() && !right->isMatrix()) { - if (right->isVector()) { - op = EOpMatrixTimesVector; - setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); - } else { - op = EOpMatrixTimesScalar; - } - } else if (left->isMatrix() && right->isMatrix()) { - op = EOpMatrixTimesMatrix; - } else if (!left->isMatrix() && !right->isMatrix()) { - if (left->isVector() && right->isVector()) { - // leave as component product - } else if (left->isVector() || right->isVector()) { - op = EOpVectorTimesScalar; - setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); - } - } else { - infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses"); - return false; + 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)); } - break; - case EOpMulAssign: - if (!left->isMatrix() && right->isMatrix()) { - if (left->isVector()) - op = EOpVectorTimesMatrixAssign; - else { - return false; - } - } else if (left->isMatrix() && !right->isMatrix()) { - if (right->isVector()) { - return false; - } else { - op = EOpMatrixTimesScalarAssign; - } - } else if (left->isMatrix() && right->isMatrix()) { - op = EOpMatrixTimesMatrixAssign; - } else if (!left->isMatrix() && !right->isMatrix()) { - if (left->isVector() && right->isVector()) { - // leave as component product - } else if (left->isVector() || right->isVector()) { - if (! left->isVector()) - return false; - op = EOpVectorTimesScalarAssign; - setType(TType(basicType, higherPrecision, EvqTemporary, size, false)); - } - } else { - infoSink.info.message(EPrefixInternalError, getLine(), "Missing elses"); - return false; + else + { + mOp = EOpMatrixTimesScalar; + setType(TType(basicType, higherPrecision, EvqTemporary, + mRight->getCols(), mRight->getRows())); } - break; + } + 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; + } - case EOpAssign: - case EOpInitialize: - case EOpAdd: - case EOpSub: - case EOpDiv: - case EOpAddAssign: - case EOpSubAssign: - case EOpDivAssign: - if ((left->isMatrix() && right->isVector()) || - (left->isVector() && right->isMatrix())) + 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; - setType(TType(basicType, higherPrecision, EvqTemporary, size, left->isMatrix() || right->isMatrix())); - break; - - case EOpEqual: - case EOpNotEqual: - case EOpLessThan: - case EOpGreaterThan: - case EOpLessThanEqual: - case EOpGreaterThanEqual: - if ((left->isMatrix() && right->isVector()) || - (left->isVector() && right->isMatrix())) + } + } + else if (mLeft->isMatrix() && !mRight->isMatrix()) + { + if (mRight->isVector()) + { return false; - setType(TType(EbtBool, EbpUndefined)); - break; - - default: - return false; - } - - return true; -} - -bool CompareStruct(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) -{ - const TFieldList& fields = leftNodeType.getStruct()->fields(); - - size_t structSize = fields.size(); - size_t index = 0; - - for (size_t j = 0; j < structSize; j++) { - size_t size = fields[j]->type()->getObjectSize(); - for (size_t i = 0; i < size; i++) { - if (fields[j]->type()->getBasicType() == EbtStruct) { - if (!CompareStructure(*(fields[j]->type()), &rightUnionArray[index], &leftUnionArray[index])) - return false; - } else { - if (leftUnionArray[index] != rightUnionArray[index]) + } + 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; - index++; + mOp = EOpVectorTimesScalarAssign; + setType(TType(basicType, higherPrecision, EvqTemporary, + mLeft->getNominalSize(), 1)); } } - } - return true; -} + else + { + infoSink.info.message(EPrefixInternalError, getLine(), + "Missing elses"); + return false; + } -bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, ConstantUnion* leftUnionArray) -{ - if (leftNodeType.isArray()) { - TType typeWithoutArrayness = leftNodeType; - typeWithoutArrayness.clearArrayness(); + 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; + } - size_t arraySize = leftNodeType.getArraySize(); + // 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; - for (size_t i = 0; i < arraySize; ++i) { - size_t offset = typeWithoutArrayness.getObjectSize() * i; - if (!CompareStruct(typeWithoutArrayness, &rightUnionArray[offset], &leftUnionArray[offset])) + // Operator cannot be of type pure assignment. + if (mOp == EOpAssign || mOp == EOpInitialize) return false; } - } else - return CompareStruct(leftNodeType, rightUnionArray, leftUnionArray); + { + 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; } @@ -1123,372 +1134,472 @@ bool CompareStructure(const TType& leftNodeType, ConstantUnion* rightUnionArray, // // 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) +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 + 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) { + 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) { + } + else if (constantNode->getType().getObjectSize() > 1 && objectSize == 1) + { // for a case like float f = vec4(2,3,4,5) + 1.2; unionArray = new ConstantUnion[constantNode->getType().getObjectSize()]; for (size_t i = 0; i < constantNode->getType().getObjectSize(); ++i) + { unionArray[i] = *getUnionArrayPointer(); + } returnType = node->getType(); objectSize = constantNode->getType().getObjectSize(); } - ConstantUnion* tempConstArray = 0; + ConstantUnion *tempConstArray = NULL; TIntermConstantUnion *tempNode; bool boolNodeFlag = false; - switch(op) { - case EOpAdd: - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] + rightUnionArray[i]; - } - break; - case EOpSub: - tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] - rightUnionArray[i]; - } - break; + 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]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] * rightUnionArray[i]; - } - break; - case EOpMatrixTimesMatrix: - if (getType().getBasicType() != EbtFloat || node->getBasicType() != EbtFloat) { - infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix multiply"); - return 0; + 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; } - {// support MSVC++6.0 - int size = getNominalSize(); - tempConstArray = new ConstantUnion[size*size]; - for (int row = 0; row < size; row++) { - for (int column = 0; column < size; column++) { - tempConstArray[size * column + row].setFConst(0.0f); - for (int i = 0; i < size; i++) { - tempConstArray[size * column + row].setFConst(tempConstArray[size * column + row].getFConst() + unionArray[i * size + row].getFConst() * (rightUnionArray[column * size + i].getFConst())); - } + + 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()); } } } - break; - case EOpDiv: + + // update return type for matrix product + returnType.setPrimarySize(resultCols); + returnType.setSecondarySize(resultRows); + } + break; + + case EOpDiv: + { tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) { - switch (getType().getBasicType()) { - case EbtFloat: - if (rightUnionArray[i] == 0.0f) { - infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding"); - tempConstArray[i].setFConst(unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX); - } else - tempConstArray[i].setFConst(unionArray[i].getFConst() / rightUnionArray[i].getFConst()); - break; + for (size_t i = 0; i < objectSize; i++) + { + switch (getType().getBasicType()) + { + case EbtFloat: + if (rightUnionArray[i] == 0.0f) + { + infoSink.info.message( + EPrefixWarning, getLine(), + "Divide by zero error during constant folding"); + tempConstArray[i].setFConst( + unionArray[i].getFConst() < 0 ? -FLT_MAX : FLT_MAX); + } + else + { + tempConstArray[i].setFConst( + unionArray[i].getFConst() / + rightUnionArray[i].getFConst()); + } + break; - case EbtInt: - if (rightUnionArray[i] == 0) { - infoSink.info.message(EPrefixWarning, getLine(), "Divide by zero error during constant folding"); - tempConstArray[i].setIConst(INT_MAX); - } else - tempConstArray[i].setIConst(unionArray[i].getIConst() / rightUnionArray[i].getIConst()); - break; - default: - infoSink.info.message(EPrefixInternalError, getLine(), "Constant folding cannot be done for \"/\""); - return 0; + 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; + } + break; - case EOpMatrixTimesVector: - if (node->getBasicType() != EbtFloat) { - infoSink.info.message(EPrefixInternalError, getLine(), "Constant Folding cannot be done for matrix times vector"); - return 0; + case EOpMatrixTimesVector: + { + if (node->getBasicType() != EbtFloat) + { + infoSink.info.message( + EPrefixInternalError, getLine(), + "Constant Folding cannot be done for matrix times vector"); + return NULL; } - tempConstArray = new ConstantUnion[getNominalSize()]; - {// support MSVC++6.0 - for (int size = getNominalSize(), i = 0; i < size; i++) { - tempConstArray[i].setFConst(0.0f); - for (int j = 0; j < size; j++) { - tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j*size + i].getFConst()) * rightUnionArray[j].getFConst())); - } + 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()); } } - tempNode = new TIntermConstantUnion(tempConstArray, node->getType()); + 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 0; + case EOpVectorTimesMatrix: + { + if (getType().getBasicType() != EbtFloat) + { + infoSink.info.message( + EPrefixInternalError, getLine(), + "Constant Folding cannot be done for vector times matrix"); + return NULL; } - tempConstArray = new ConstantUnion[getNominalSize()]; - {// support MSVC++6.0 - for (int size = getNominalSize(), i = 0; i < size; i++) { - tempConstArray[i].setFConst(0.0f); - for (int j = 0; j < size; j++) { - tempConstArray[i].setFConst(tempConstArray[i].getFConst() + ((unionArray[j].getFConst()) * rightUnionArray[i*size + j].getFConst())); - } + 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()); } } - break; - case EOpLogicalAnd: // this code is written for possible future use, will not get executed currently + returnType.setPrimarySize(matrixCols); + } + break; + + case EOpLogicalAnd: + // this code is written for possible future use, + // will not get executed currently + { tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] && rightUnionArray[i]; + for (size_t i = 0; i < objectSize; i++) + { + tempConstArray[i] = unionArray[i] && rightUnionArray[i]; } - break; + } + break; - case EOpLogicalOr: // this code is written for possible future use, will not get executed currently + case EOpLogicalOr: + // this code is written for possible future use, + // will not get executed currently + { tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) - tempConstArray[i] = unionArray[i] || rightUnionArray[i]; + for (size_t i = 0; i < objectSize; i++) + { + tempConstArray[i] = unionArray[i] || rightUnionArray[i]; } - break; + } + break; - case EOpLogicalXor: + case EOpLogicalXor: + { tempConstArray = new ConstantUnion[objectSize]; - {// support MSVC++6.0 - for (size_t i = 0; i < objectSize; i++) - switch (getType().getBasicType()) { - case EbtBool: tempConstArray[i].setBConst((unionArray[i] == rightUnionArray[i]) ? false : true); break; - default: assert(false && "Default missing"); + 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; + } + break; + + case EOpLessThan: + ASSERT(objectSize == 1); + tempConstArray = new ConstantUnion[1]; + tempConstArray->setBConst(*unionArray < *rightUnionArray); + returnType = TType(EbtBool, EbpUndefined, EvqConst); + break; - case EOpLessThan: - assert(objectSize == 1); + 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(*unionArray < *rightUnionArray); + tempConstArray->setBConst(!constant.getBConst()); returnType = TType(EbtBool, EbpUndefined, EvqConst); break; - case EOpGreaterThan: - assert(objectSize == 1); + } + + case EOpGreaterThanEqual: + { + ASSERT(objectSize == 1); + ConstantUnion constant; + constant.setBConst(*unionArray < *rightUnionArray); tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(*unionArray > *rightUnionArray); + tempConstArray->setBConst(!constant.getBConst()); returnType = TType(EbtBool, EbpUndefined, EvqConst); break; - case EOpLessThanEqual: + } + + case EOpEqual: + if (getType().getBasicType() == EbtStruct) + { + if (!CompareStructure(node->getType(), + node->getUnionArrayPointer(), + unionArray)) { - assert(objectSize == 1); - ConstantUnion constant; - constant.setBConst(*unionArray > *rightUnionArray); - tempConstArray = new ConstantUnion[1]; - tempConstArray->setBConst(!constant.getBConst()); - returnType = TType(EbtBool, EbpUndefined, EvqConst); - break; + boolNodeFlag = true; } - case EOpGreaterThanEqual: + } + else + { + for (size_t i = 0; i < objectSize; i++) { - 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)) + if (unionArray[i] != rightUnionArray[i]) + { boolNodeFlag = true; - } else { - for (size_t i = 0; i < objectSize; i++) { - if (unionArray[i] != rightUnionArray[i]) { - boolNodeFlag = true; - break; // break out of for loop - } + break; // break out of for loop } } + } - tempConstArray = new ConstantUnion[1]; - if (!boolNodeFlag) { - tempConstArray->setBConst(true); - } - else { - tempConstArray->setBConst(false); - } + tempConstArray = new ConstantUnion[1]; + if (!boolNodeFlag) + { + tempConstArray->setBConst(true); + } + else + { + tempConstArray->setBConst(false); + } - tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); - tempNode->setLine(getLine()); + tempNode = new TIntermConstantUnion( + tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); + tempNode->setLine(getLine()); - return tempNode; + return tempNode; - case EOpNotEqual: - if (getType().getBasicType() == EbtStruct) { - if (CompareStructure(node->getType(), node->getUnionArrayPointer(), unionArray)) + 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; - } else { - for (size_t i = 0; i < objectSize; i++) { - if (unionArray[i] == rightUnionArray[i]) { - boolNodeFlag = true; - break; // break out of for loop - } + break; // break out of for loop } } + } - tempConstArray = new ConstantUnion[1]; - if (!boolNodeFlag) { - tempConstArray->setBConst(true); - } - else { - tempConstArray->setBConst(false); - } + tempConstArray = new ConstantUnion[1]; + if (!boolNodeFlag) + { + tempConstArray->setBConst(true); + } + else + { + tempConstArray->setBConst(false); + } - tempNode = new TIntermConstantUnion(tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); - tempNode->setLine(getLine()); + tempNode = new TIntermConstantUnion( + tempConstArray, TType(EbtBool, EbpUndefined, EvqConst)); + tempNode->setLine(getLine()); - return tempNode; + return tempNode; - default: - infoSink.info.message(EPrefixInternalError, getLine(), "Invalid operator for constant folding"); - return 0; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Invalid operator for constant folding"); + return NULL; } tempNode = new TIntermConstantUnion(tempConstArray, returnType); tempNode->setLine(getLine()); return tempNode; - } else { + } + else + { // // Do unary operations // TIntermConstantUnion *newNode = 0; ConstantUnion* tempConstArray = new ConstantUnion[objectSize]; - for (size_t i = 0; i < objectSize; i++) { - switch(op) { - case EOpNegative: - switch (getType().getBasicType()) { - case EbtFloat: tempConstArray[i].setFConst(-unionArray[i].getFConst()); break; - case EbtInt: tempConstArray[i].setIConst(-unionArray[i].getIConst()); break; - default: - infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); - return 0; - } + 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 EOpLogicalNot: // this code is written for possible future use, will not get executed currently - switch (getType().getBasicType()) { - case EbtBool: tempConstArray[i].setBConst(!unionArray[i].getBConst()); break; - default: - infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant"); - return 0; - } + case EbtInt: + tempConstArray[i].setIConst(-unionArray[i].getIConst()); break; - default: - return 0; - } - } - newNode = new TIntermConstantUnion(tempConstArray, getType()); - newNode->setLine(getLine()); - return newNode; - } -} - -TIntermTyped* TIntermediate::promoteConstantUnion(TBasicType promoteTo, TIntermConstantUnion* node) -{ - size_t size = node->getType().getObjectSize(); - - ConstantUnion *leftUnionArray = new ConstantUnion[size]; - - for (size_t i = 0; i < size; i++) { - - switch (promoteTo) { - case EbtFloat: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setFConst(static_cast(node->getIConst(i))); - break; - case EbtBool: - leftUnionArray[i].setFConst(static_cast(node->getBConst(i))); - break; - case EbtFloat: - leftUnionArray[i].setFConst(static_cast(node->getFConst(i))); - break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); - return 0; + 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 EbtInt: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setIConst(static_cast(node->getIConst(i))); - break; - case EbtBool: - leftUnionArray[i].setIConst(static_cast(node->getBConst(i))); - break; - case EbtFloat: - leftUnionArray[i].setIConst(static_cast(node->getFConst(i))); - break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); - return 0; + + 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; - case EbtBool: - switch (node->getType().getBasicType()) { - case EbtInt: - leftUnionArray[i].setBConst(node->getIConst(i) != 0); - break; - case EbtBool: - leftUnionArray[i].setBConst(node->getBConst(i)); - break; - case EbtFloat: - leftUnionArray[i].setBConst(node->getFConst(i) != 0.0f); - break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Cannot promote"); - return 0; - } - break; - default: - infoSink.info.message(EPrefixInternalError, node->getLine(), "Incorrect data type found"); - return 0; + default: + return NULL; + } } - + newNode = new TIntermConstantUnion(tempConstArray, getType()); + newNode->setLine(getLine()); + return newNode; } - - const TType& t = node->getType(); - - return addConstantUnion(leftUnionArray, TType(promoteTo, t.getPrecision(), t.getQualifier(), t.getNominalSize(), t.isMatrix(), t.isArray()), node->getLine()); } // static -TString TIntermTraverser::hash(const TString& name, ShHashFunction64 hashFunction) +TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunction) { if (hashFunction == NULL || name.empty()) return name; diff --git a/src/3rdparty/angle/src/compiler/translator/LoopInfo.cpp b/src/3rdparty/angle/src/compiler/translator/LoopInfo.cpp new file mode 100644 index 0000000000..d931a18a23 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/LoopInfo.cpp @@ -0,0 +1,211 @@ +// +// 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/LoopInfo.h" + +namespace +{ + +int EvaluateIntConstant(TIntermConstantUnion *node) +{ + ASSERT(node && node->getUnionArrayPointer()); + return node->getIConst(0); +} + +int GetLoopIntIncrement(TIntermLoop *node) +{ + TIntermNode *expr = node->getExpression(); + // for expression has one of the following forms: + // loop_index++ + // loop_index-- + // loop_index += constant_expression + // loop_index -= constant_expression + // ++loop_index + // --loop_index + // The last two forms are not specified in the spec, but I am assuming + // its an oversight. + TIntermUnary *unOp = expr->getAsUnaryNode(); + TIntermBinary *binOp = unOp ? NULL : expr->getAsBinaryNode(); + + TOperator op = EOpNull; + TIntermConstantUnion *incrementNode = NULL; + if (unOp) + { + op = unOp->getOp(); + } + else if (binOp) + { + op = binOp->getOp(); + ASSERT(binOp->getRight()); + incrementNode = binOp->getRight()->getAsConstantUnion(); + ASSERT(incrementNode); + } + + int increment = 0; + // The operator is one of: ++ -- += -=. + switch (op) + { + case EOpPostIncrement: + case EOpPreIncrement: + ASSERT(unOp && !binOp); + increment = 1; + break; + case EOpPostDecrement: + case EOpPreDecrement: + ASSERT(unOp && !binOp); + increment = -1; + break; + case EOpAddAssign: + ASSERT(!unOp && binOp); + increment = EvaluateIntConstant(incrementNode); + break; + case EOpSubAssign: + ASSERT(!unOp && binOp); + increment = - EvaluateIntConstant(incrementNode); + break; + default: + UNREACHABLE(); + } + + return increment; +} + +} // namespace anonymous + +TLoopIndexInfo::TLoopIndexInfo() + : mId(-1), + mType(EbtVoid), + mInitValue(0), + mStopValue(0), + mIncrementValue(0), + mOp(EOpNull), + mCurrentValue(0) +{ +} + +void TLoopIndexInfo::fillInfo(TIntermLoop *node) +{ + if (node == NULL) + return; + + // Here we assume all the operations are valid, because the loop node is + // already validated in ValidateLimitations. + TIntermSequence *declSeq = + node->getInit()->getAsAggregate()->getSequence(); + TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); + TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); + + mId = symbol->getId(); + mType = symbol->getBasicType(); + + if (mType == EbtInt) + { + TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion(); + mInitValue = EvaluateIntConstant(initNode); + mCurrentValue = mInitValue; + mIncrementValue = GetLoopIntIncrement(node); + + TIntermBinary* binOp = node->getCondition()->getAsBinaryNode(); + mStopValue = EvaluateIntConstant( + binOp->getRight()->getAsConstantUnion()); + mOp = binOp->getOp(); + } +} + +bool TLoopIndexInfo::satisfiesLoopCondition() const +{ + // Relational operator is one of: > >= < <= == or !=. + switch (mOp) + { + case EOpEqual: + return (mCurrentValue == mStopValue); + case EOpNotEqual: + return (mCurrentValue != mStopValue); + case EOpLessThan: + return (mCurrentValue < mStopValue); + case EOpGreaterThan: + return (mCurrentValue > mStopValue); + case EOpLessThanEqual: + return (mCurrentValue <= mStopValue); + case EOpGreaterThanEqual: + return (mCurrentValue >= mStopValue); + default: + UNREACHABLE(); + return false; + } +} + +TLoopInfo::TLoopInfo() + : loop(NULL) +{ +} + +TLoopInfo::TLoopInfo(TIntermLoop *node) + : loop(node) +{ + index.fillInfo(node); +} + +TIntermLoop *TLoopStack::findLoop(TIntermSymbol *symbol) +{ + if (!symbol) + return NULL; + for (iterator iter = begin(); iter != end(); ++iter) + { + if (iter->index.getId() == symbol->getId()) + return iter->loop; + } + return NULL; +} + +TLoopIndexInfo *TLoopStack::getIndexInfo(TIntermSymbol *symbol) +{ + if (!symbol) + return NULL; + for (iterator iter = begin(); iter != end(); ++iter) + { + if (iter->index.getId() == symbol->getId()) + return &(iter->index); + } + return NULL; +} + +void TLoopStack::step() +{ + ASSERT(!empty()); + rbegin()->index.step(); +} + +bool TLoopStack::satisfiesLoopCondition() +{ + ASSERT(!empty()); + return rbegin()->index.satisfiesLoopCondition(); +} + +bool TLoopStack::needsToReplaceSymbolWithValue(TIntermSymbol *symbol) +{ + TIntermLoop *loop = findLoop(symbol); + return loop && loop->getUnrollFlag(); +} + +int TLoopStack::getLoopIndexValue(TIntermSymbol *symbol) +{ + TLoopIndexInfo *info = getIndexInfo(symbol); + ASSERT(info); + return info->getCurrentValue(); +} + +void TLoopStack::push(TIntermLoop *loop) +{ + TLoopInfo info(loop); + push_back(info); +} + +void TLoopStack::pop() +{ + pop_back(); +} + diff --git a/src/3rdparty/angle/src/compiler/translator/LoopInfo.h b/src/3rdparty/angle/src/compiler/translator/LoopInfo.h new file mode 100644 index 0000000000..5a140c339e --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/LoopInfo.h @@ -0,0 +1,80 @@ +// +// 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_LOOP_INFO_H_ +#define COMPILER_TRANSLATOR_LOOP_INFO_H_ + +#include "compiler/translator/intermediate.h" + +class TLoopIndexInfo +{ + public: + TLoopIndexInfo(); + + // If type is EbtInt, fill all fields of the structure with info + // extracted from a loop node. + // If type is not EbtInt, only fill id and type. + void fillInfo(TIntermLoop *node); + + int getId() const { return mId; } + void setId(int id) { mId = id; } + TBasicType getType() const { return mType; } + void setType(TBasicType type) { mType = type; } + int getCurrentValue() const { return mCurrentValue; } + + void step() { mCurrentValue += mIncrementValue; } + + // Check if the current value satisfies the loop condition. + bool satisfiesLoopCondition() const; + + private: + int mId; + TBasicType mType; // Either EbtInt or EbtFloat + + // Below fields are only valid if the index's type is int. + int mInitValue; + int mStopValue; + int mIncrementValue; + TOperator mOp; + int mCurrentValue; +}; + +struct TLoopInfo +{ + TLoopIndexInfo index; + TIntermLoop *loop; + + TLoopInfo(); + TLoopInfo(TIntermLoop *node); +}; + +class TLoopStack : public TVector +{ + public: + // Search loop stack for a loop whose index matches the input symbol. + TIntermLoop *findLoop(TIntermSymbol *symbol); + + // Find the loop index info in the loop stack by the input symbol. + TLoopIndexInfo *getIndexInfo(TIntermSymbol *symbol); + + // Update the currentValue for the next loop iteration. + void step(); + + // Return false if loop condition is no longer satisfied. + bool satisfiesLoopCondition(); + + // Check if the symbol is the index of a loop that's unrolled. + bool needsToReplaceSymbolWithValue(TIntermSymbol *symbol); + + // Return the current value of a given loop index symbol. + int getLoopIndexValue(TIntermSymbol *symbol); + + void push(TIntermLoop *info); + void pop(); +}; + +#endif // COMPILER_TRANSLATOR_LOOP_INDEX_H_ + diff --git a/src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.cpp b/src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.cpp deleted file mode 100644 index ef629c26b1..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/MapLongVariableNames.h" - -namespace { - -TString mapLongName(size_t id, const TString& name, bool isGlobal) -{ - ASSERT(name.size() > MAX_SHORTENED_IDENTIFIER_SIZE); - TStringStream stream; - stream << "webgl_"; - if (isGlobal) - stream << "g"; - stream << id; - if (name[0] != '_') - stream << "_"; - stream << name.substr(0, MAX_SHORTENED_IDENTIFIER_SIZE - stream.str().size()); - return stream.str(); -} - -LongNameMap* gLongNameMapInstance = NULL; - -} // anonymous namespace - -LongNameMap::LongNameMap() - : refCount(0) -{ -} - -LongNameMap::~LongNameMap() -{ -} - -// static -LongNameMap* LongNameMap::GetInstance() -{ - if (gLongNameMapInstance == NULL) - gLongNameMapInstance = new LongNameMap; - gLongNameMapInstance->refCount++; - return gLongNameMapInstance; -} - -void LongNameMap::Release() -{ - ASSERT(gLongNameMapInstance == this); - ASSERT(refCount > 0); - refCount--; - if (refCount == 0) { - delete gLongNameMapInstance; - gLongNameMapInstance = NULL; - } -} - -const char* LongNameMap::Find(const char* originalName) const -{ - std::map::const_iterator it = mLongNameMap.find( - originalName); - if (it != mLongNameMap.end()) - return (*it).second.c_str(); - return NULL; -} - -void LongNameMap::Insert(const char* originalName, const char* mappedName) -{ - mLongNameMap.insert(std::map::value_type( - originalName, mappedName)); -} - -size_t LongNameMap::Size() const -{ - return mLongNameMap.size(); -} - -MapLongVariableNames::MapLongVariableNames(LongNameMap* globalMap) -{ - ASSERT(globalMap); - mGlobalMap = globalMap; -} - -void MapLongVariableNames::visitSymbol(TIntermSymbol* symbol) -{ - ASSERT(symbol != NULL); - if (symbol->getSymbol().size() > MAX_SHORTENED_IDENTIFIER_SIZE) { - switch (symbol->getQualifier()) { - case EvqVaryingIn: - case EvqVaryingOut: - case EvqInvariantVaryingIn: - case EvqInvariantVaryingOut: - case EvqUniform: - symbol->setSymbol( - mapGlobalLongName(symbol->getSymbol())); - break; - default: - symbol->setSymbol( - mapLongName(symbol->getId(), symbol->getSymbol(), false)); - break; - }; - } -} - -TString MapLongVariableNames::mapGlobalLongName(const TString& name) -{ - ASSERT(mGlobalMap); - const char* mappedName = mGlobalMap->Find(name.c_str()); - if (mappedName != NULL) - return mappedName; - size_t id = mGlobalMap->Size(); - TString rt = mapLongName(id, name, true); - mGlobalMap->Insert(name.c_str(), rt.c_str()); - return rt; -} diff --git a/src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.h b/src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.h deleted file mode 100644 index 3b085a3687..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/MapLongVariableNames.h +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_MAP_LONG_VARIABLE_NAMES_H_ -#define COMPILER_MAP_LONG_VARIABLE_NAMES_H_ - -#include "GLSLANG/ShaderLang.h" - -#include "compiler/translator/intermediate.h" -#include "compiler/translator/VariableInfo.h" - -// This size does not include '\0' in the end. -#define MAX_SHORTENED_IDENTIFIER_SIZE 32 - -// This is a ref-counted singleton. GetInstance() returns a pointer to the -// singleton, and after use, call Release(). GetInstance() and Release() should -// be paired. -class LongNameMap { -public: - static LongNameMap* GetInstance(); - void Release(); - - // Return the mapped name if is in the map; - // otherwise, return NULL. - const char* Find(const char* originalName) const; - - // Insert a pair into the map. - void Insert(const char* originalName, const char* mappedName); - - // Return the number of entries in the map. - size_t Size() const; - -private: - LongNameMap(); - ~LongNameMap(); - - size_t refCount; - std::map mLongNameMap; -}; - -// Traverses intermediate tree to map attributes and uniforms names that are -// longer than MAX_SHORTENED_IDENTIFIER_SIZE to MAX_SHORTENED_IDENTIFIER_SIZE. -class MapLongVariableNames : public TIntermTraverser { -public: - MapLongVariableNames(LongNameMap* globalMap); - - virtual void visitSymbol(TIntermSymbol*); - -private: - TString mapGlobalLongName(const TString& name); - - LongNameMap* mGlobalMap; -}; - -#endif // COMPILER_MAP_LONG_VARIABLE_NAMES_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp index 8367412462..65635af1ff 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -10,8 +10,9 @@ TOutputESSL::TOutputESSL(TInfoSinkBase& objSink, ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, NameMap& nameMap, - TSymbolTable& symbolTable) - : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable) + TSymbolTable& symbolTable, + int shaderVersion) + : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable, shaderVersion) { } diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h index 2f02979a05..8a567fb8aa 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -16,7 +16,8 @@ public: ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, NameMap& nameMap, - TSymbolTable& symbolTable); + TSymbolTable& symbolTable, + int shaderVersion); protected: virtual bool writeVariablePrecision(TPrecision precision); diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp index 5589560682..eb7cbb4ae8 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -10,8 +10,9 @@ TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink, ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, NameMap& nameMap, - TSymbolTable& symbolTable) - : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable) + TSymbolTable& symbolTable, + int shaderVersion) + : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable, shaderVersion) { } @@ -33,3 +34,24 @@ void TOutputGLSL::visitSymbol(TIntermSymbol* node) TOutputGLSLBase::visitSymbol(node); } } + +TString TOutputGLSL::translateTextureFunction(TString& name) +{ + static const char *simpleRename[] = { + "texture2DLodEXT", "texture2DLod", + "texture2DProjLodEXT", "texture2DProjLod", + "textureCubeLodEXT", "textureCubeLod", + "texture2DGradEXT", "texture2DGradARB", + "texture2DProjGradEXT", "texture2DProjGradARB", + "textureCubeGradEXT", "textureCubeGradARB", + NULL, NULL + }; + + for (int i = 0; simpleRename[i] != NULL; i += 2) { + if (name == simpleRename[i]) { + return simpleRename[i+1]; + } + } + + return name; +} diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h index e1f114d347..bceebe397d 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -16,11 +16,13 @@ public: ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, NameMap& nameMap, - TSymbolTable& symbolTable); + TSymbolTable& symbolTable, + int shaderVersion); protected: virtual bool writeVariablePrecision(TPrecision); virtual void visitSymbol(TIntermSymbol* node); + virtual TString translateTextureFunction(TString& name); }; #endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp index f2f0a3d6be..7839c04852 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2011 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,7 +11,7 @@ namespace { -TString arrayBrackets(const TType& type) +TString arrayBrackets(const TType &type) { ASSERT(type.isArray()); TInfoSinkBase out; @@ -19,13 +19,14 @@ TString arrayBrackets(const TType& type) return TString(out.c_str()); } -bool isSingleStatement(TIntermNode* node) { - if (const TIntermAggregate* aggregate = node->getAsAggregate()) +bool isSingleStatement(TIntermNode *node) +{ + if (const TIntermAggregate *aggregate = node->getAsAggregate()) { return (aggregate->getOp() != EOpFunction) && (aggregate->getOp() != EOpSequence); } - else if (const TIntermSelection* selection = node->getAsSelectionNode()) + else if (const TIntermSelection *selection = node->getAsSelectionNode()) { // Ternary operators are usually part of an assignment operator. // This handles those rare cases in which they are all by themselves. @@ -39,49 +40,61 @@ bool isSingleStatement(TIntermNode* node) { } } // namespace -TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink, +TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, - NameMap& nameMap, - TSymbolTable& symbolTable) + NameMap &nameMap, + TSymbolTable &symbolTable, + int shaderVersion) : TIntermTraverser(true, true, true), mObjSink(objSink), mDeclaringVariables(false), mClampingStrategy(clampingStrategy), mHashFunction(hashFunction), mNameMap(nameMap), - mSymbolTable(symbolTable) + mSymbolTable(symbolTable), + mShaderVersion(shaderVersion) { } -void TOutputGLSLBase::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr) +void TOutputGLSLBase::writeTriplet( + Visit visit, const char *preStr, const char *inStr, const char *postStr) { - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); if (visit == PreVisit && preStr) - { out << preStr; - } else if (visit == InVisit && inStr) - { out << inStr; - } else if (visit == PostVisit && postStr) - { out << postStr; - } } -void TOutputGLSLBase::writeVariableType(const TType& type) +void TOutputGLSLBase::writeBuiltInFunctionTriplet( + Visit visit, const char *preStr, bool useEmulatedFunction) +{ + TString preString = useEmulatedFunction ? + BuiltInFunctionEmulator::GetEmulatedFunctionName(preStr) : preStr; + writeTriplet(visit, preString.c_str(), ", ", ")"); +} + +void TOutputGLSLBase::writeVariableType(const TType &type) { - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); TQualifier qualifier = type.getQualifier(); // TODO(alokp): Validate qualifier for variable declarations. - if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal)) + 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())) + if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct())) { - declareStruct(type.getStruct()); + TStructure *structure = type.getStruct(); + + declareStruct(structure); + + if (!structure->name().empty()) + { + mDeclaredStructs.insert(structure->uniqueId()); + } } else { @@ -91,19 +104,19 @@ void TOutputGLSLBase::writeVariableType(const TType& type) } } -void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence& args) +void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args) { - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); for (TIntermSequence::const_iterator iter = args.begin(); iter != args.end(); ++iter) { - const TIntermSymbol* arg = (*iter)->getAsSymbolNode(); + const TIntermSymbol *arg = (*iter)->getAsSymbolNode(); ASSERT(arg != NULL); - const TType& type = arg->getType(); + const TType &type = arg->getType(); writeVariableType(type); - const TString& name = arg->getSymbol(); + const TString &name = arg->getSymbol(); if (!name.empty()) out << " " << hashName(name); if (type.isArray()) @@ -115,23 +128,24 @@ void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence& args) } } -const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type, - const ConstantUnion* pConstUnion) +const ConstantUnion *TOutputGLSLBase::writeConstantUnion( + const TType &type, const ConstantUnion *pConstUnion) { - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); if (type.getBasicType() == EbtStruct) { - const TStructure* structure = type.getStruct(); + const TStructure *structure = type.getStruct(); out << hashName(structure->name()) << "("; - const TFieldList& fields = structure->fields(); + const TFieldList &fields = structure->fields(); for (size_t i = 0; i < fields.size(); ++i) { - const TType* fieldType = fields[i]->type(); + const TType *fieldType = fields[i]->type(); ASSERT(fieldType != NULL); pConstUnion = writeConstantUnion(*fieldType, pConstUnion); - if (i != fields.size() - 1) out << ", "; + if (i != fields.size() - 1) + out << ", "; } out << ")"; } @@ -139,28 +153,37 @@ const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type, { size_t size = type.getObjectSize(); bool writeType = size > 1; - if (writeType) out << getTypeName(type) << "("; + if (writeType) + out << getTypeName(type) << "("; for (size_t i = 0; i < size; ++i, ++pConstUnion) { switch (pConstUnion->getType()) { - case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, pConstUnion->getFConst())); break; - case EbtInt: out << pConstUnion->getIConst(); break; - case EbtBool: out << pConstUnion->getBConst(); break; - default: UNREACHABLE(); + case EbtFloat: + out << std::min(FLT_MAX, std::max(-FLT_MAX, pConstUnion->getFConst())); + break; + case EbtInt: + out << pConstUnion->getIConst(); + break; + case EbtBool: + out << pConstUnion->getBConst(); + break; + default: UNREACHABLE(); } - if (i != size - 1) out << ", "; + if (i != size - 1) + out << ", "; } - if (writeType) out << ")"; + if (writeType) + out << ")"; } return pConstUnion; } -void TOutputGLSLBase::visitSymbol(TIntermSymbol* node) +void TOutputGLSLBase::visitSymbol(TIntermSymbol *node) { - TInfoSinkBase& out = objSink(); - if (mLoopUnroll.NeedsToReplaceSymbolWithValue(node)) - out << mLoopUnroll.GetLoopIndexValue(node); + TInfoSinkBase &out = objSink(); + if (mLoopUnrollStack.needsToReplaceSymbolWithValue(node)) + out << mLoopUnrollStack.getLoopIndexValue(node); else out << hashVariableName(node->getSymbol()); @@ -168,240 +191,303 @@ void TOutputGLSLBase::visitSymbol(TIntermSymbol* node) out << arrayBrackets(node->getType()); } -void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion* node) +void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion *node) { writeConstantUnion(node->getType(), node->getUnionArrayPointer()); } -bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) +bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) { bool visitChildren = true; - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); switch (node->getOp()) { - case EOpInitialize: + case EOpInitialize: + if (visit == InVisit) + { + out << " = "; + // RHS of initialize is not being declared. + mDeclaringVariables = false; + } + break; + case EOpAssign: + writeTriplet(visit, "(", " = ", ")"); + break; + case EOpAddAssign: + writeTriplet(visit, "(", " += ", ")"); + break; + case EOpSubAssign: + writeTriplet(visit, "(", " -= ", ")"); + break; + case EOpDivAssign: + writeTriplet(visit, "(", " /= ", ")"); + break; + // Notice the fall-through. + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + writeTriplet(visit, "(", " *= ", ")"); + break; + + case EOpIndexDirect: + writeTriplet(visit, NULL, "[", "]"); + break; + case EOpIndexIndirect: + if (node->getAddIndexClamp()) + { if (visit == InVisit) { - out << " = "; - // RHS of initialize is not being declared. - mDeclaringVariables = false; + if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) + out << "[int(clamp(float("; + else + out << "[webgl_int_clamp("; } - break; - case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break; - case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break; - case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break; - case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break; - // Notice the fall-through. - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - writeTriplet(visit, "(", " *= ", ")"); - break; - - case EOpIndexDirect: - writeTriplet(visit, NULL, "[", "]"); - break; - case EOpIndexIndirect: - if (node->getAddIndexClamp()) + else if (visit == PostVisit) { - if (visit == InVisit) + int maxSize; + TIntermTyped *left = node->getLeft(); + TType leftType = left->getType(); + + if (left->isArray()) { - if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) { - out << "[int(clamp(float("; - } else { - out << "[webgl_int_clamp("; - } + // The shader will fail validation if the array length is not > 0. + maxSize = leftType.getArraySize() - 1; } - else if (visit == PostVisit) + else { - int maxSize; - TIntermTyped *left = node->getLeft(); - TType leftType = left->getType(); - - if (left->isArray()) - { - // The shader will fail validation if the array length is not > 0. - maxSize = leftType.getArraySize() - 1; - } - else - { - maxSize = leftType.getNominalSize() - 1; - } - - if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) { - out << "), 0.0, float(" << maxSize << ")))]"; - } else { - out << ", 0, " << maxSize << ")]"; - } + maxSize = leftType.getNominalSize() - 1; } + + if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) + out << "), 0.0, float(" << maxSize << ")))]"; + else + out << ", 0, " << maxSize << ")]"; } - else - { - writeTriplet(visit, NULL, "[", "]"); - } - break; - case EOpIndexDirectStruct: - if (visit == InVisit) - { - // Here we are writing out "foo.bar", where "foo" is struct - // and "bar" is field. In AST, it is represented as a binary - // node, where left child represents "foo" and right child "bar". - // The node itself represents ".". The struct field "bar" is - // actually stored as an index into TStructure::fields. - out << "."; - const TStructure* structure = node->getLeft()->getType().getStruct(); - const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion(); - const TField* field = structure->fields()[index->getIConst(0)]; - - TString fieldName = field->name(); - if (!mSymbolTable.findBuiltIn(structure->name())) - fieldName = hashName(fieldName); - - out << fieldName; - visitChildren = false; - } - break; - case EOpVectorSwizzle: - if (visit == InVisit) + } + else + { + writeTriplet(visit, NULL, "[", "]"); + } + break; + case EOpIndexDirectStruct: + if (visit == InVisit) + { + // Here we are writing out "foo.bar", where "foo" is struct + // and "bar" is field. In AST, it is represented as a binary + // node, where left child represents "foo" and right child "bar". + // The node itself represents ".". The struct field "bar" is + // actually stored as an index into TStructure::fields. + out << "."; + const TStructure *structure = node->getLeft()->getType().getStruct(); + const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); + const TField *field = structure->fields()[index->getIConst(0)]; + + TString fieldName = field->name(); + if (!mSymbolTable.findBuiltIn(structure->name(), mShaderVersion)) + fieldName = hashName(fieldName); + + out << fieldName; + visitChildren = false; + } + break; + case EOpVectorSwizzle: + if (visit == InVisit) + { + out << "."; + TIntermAggregate *rightChild = node->getRight()->getAsAggregate(); + TIntermSequence *sequence = rightChild->getSequence(); + for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); ++sit) { - out << "."; - TIntermAggregate* rightChild = node->getRight()->getAsAggregate(); - TIntermSequence& sequence = rightChild->getSequence(); - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit) + TIntermConstantUnion *element = (*sit)->getAsConstantUnion(); + ASSERT(element->getBasicType() == EbtInt); + ASSERT(element->getNominalSize() == 1); + const ConstantUnion& data = element->getUnionArrayPointer()[0]; + ASSERT(data.getType() == EbtInt); + switch (data.getIConst()) { - TIntermConstantUnion* element = (*sit)->getAsConstantUnion(); - ASSERT(element->getBasicType() == EbtInt); - ASSERT(element->getNominalSize() == 1); - const ConstantUnion& data = element->getUnionArrayPointer()[0]; - ASSERT(data.getType() == EbtInt); - switch (data.getIConst()) - { - case 0: out << "x"; break; - case 1: out << "y"; break; - case 2: out << "z"; break; - case 3: out << "w"; break; - default: UNREACHABLE(); break; - } + case 0: + out << "x"; + break; + case 1: + out << "y"; + break; + case 2: + out << "z"; + break; + case 3: + out << "w"; + break; + default: + UNREACHABLE(); } - visitChildren = false; } - break; - - case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break; - case EOpSub: writeTriplet(visit, "(", " - ", ")"); break; - case EOpMul: writeTriplet(visit, "(", " * ", ")"); break; - case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break; - case EOpMod: UNIMPLEMENTED(); break; - case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break; - case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break; - case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break; - case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break; - case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break; - case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break; - - // Notice the fall-through. - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpMatrixTimesMatrix: - writeTriplet(visit, "(", " * ", ")"); - break; - - case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break; - case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break; - case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break; - default: UNREACHABLE(); break; + visitChildren = false; + } + break; + + case EOpAdd: + writeTriplet(visit, "(", " + ", ")"); + break; + case EOpSub: + writeTriplet(visit, "(", " - ", ")"); + break; + case EOpMul: + writeTriplet(visit, "(", " * ", ")"); + break; + case EOpDiv: + writeTriplet(visit, "(", " / ", ")"); + break; + case EOpMod: + UNIMPLEMENTED(); + break; + case EOpEqual: + writeTriplet(visit, "(", " == ", ")"); + break; + case EOpNotEqual: + writeTriplet(visit, "(", " != ", ")"); + break; + case EOpLessThan: + writeTriplet(visit, "(", " < ", ")"); + break; + case EOpGreaterThan: + writeTriplet(visit, "(", " > ", ")"); + break; + case EOpLessThanEqual: + writeTriplet(visit, "(", " <= ", ")"); + break; + case EOpGreaterThanEqual: + writeTriplet(visit, "(", " >= ", ")"); + break; + + // Notice the fall-through. + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: + writeTriplet(visit, "(", " * ", ")"); + break; + + case EOpLogicalOr: + writeTriplet(visit, "(", " || ", ")"); + break; + case EOpLogicalXor: + writeTriplet(visit, "(", " ^^ ", ")"); + break; + case EOpLogicalAnd: + writeTriplet(visit, "(", " && ", ")"); + break; + default: + UNREACHABLE(); } return visitChildren; } -bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node) +bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) { TString preString; TString postString = ")"; switch (node->getOp()) { - case EOpNegative: preString = "(-"; break; - case EOpVectorLogicalNot: preString = "not("; break; - case EOpLogicalNot: preString = "(!"; break; - - case EOpPostIncrement: preString = "("; postString = "++)"; break; - case EOpPostDecrement: preString = "("; postString = "--)"; break; - case EOpPreIncrement: preString = "(++"; break; - case EOpPreDecrement: preString = "(--"; break; - - case EOpConvIntToBool: - case EOpConvFloatToBool: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: preString = "bool("; break; - case 2: preString = "bvec2("; break; - case 3: preString = "bvec3("; break; - case 4: preString = "bvec4("; break; - default: UNREACHABLE(); - } - break; - case EOpConvBoolToFloat: - case EOpConvIntToFloat: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: preString = "float("; break; - case 2: preString = "vec2("; break; - case 3: preString = "vec3("; break; - case 4: preString = "vec4("; break; - default: UNREACHABLE(); - } - break; - case EOpConvFloatToInt: - case EOpConvBoolToInt: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: preString = "int("; break; - case 2: preString = "ivec2("; break; - case 3: preString = "ivec3("; break; - case 4: preString = "ivec4("; break; - default: UNREACHABLE(); - } - break; - - case EOpRadians: preString = "radians("; break; - case EOpDegrees: preString = "degrees("; break; - case EOpSin: preString = "sin("; break; - case EOpCos: preString = "cos("; break; - case EOpTan: preString = "tan("; break; - case EOpAsin: preString = "asin("; break; - case EOpAcos: preString = "acos("; break; - case EOpAtan: preString = "atan("; break; - - case EOpExp: preString = "exp("; break; - case EOpLog: preString = "log("; break; - case EOpExp2: preString = "exp2("; break; - case EOpLog2: preString = "log2("; break; - case EOpSqrt: preString = "sqrt("; break; - case EOpInverseSqrt: preString = "inversesqrt("; break; - - case EOpAbs: preString = "abs("; break; - case EOpSign: preString = "sign("; break; - case EOpFloor: preString = "floor("; break; - case EOpCeil: preString = "ceil("; break; - case EOpFract: preString = "fract("; break; - - case EOpLength: preString = "length("; break; - case EOpNormalize: preString = "normalize("; break; - - case EOpDFdx: preString = "dFdx("; break; - case EOpDFdy: preString = "dFdy("; break; - case EOpFwidth: preString = "fwidth("; break; - - case EOpAny: preString = "any("; break; - case EOpAll: preString = "all("; break; - - default: UNREACHABLE(); break; + case EOpNegative: preString = "(-"; break; + case EOpVectorLogicalNot: preString = "not("; break; + case EOpLogicalNot: preString = "(!"; break; + + case EOpPostIncrement: preString = "("; postString = "++)"; break; + case EOpPostDecrement: preString = "("; postString = "--)"; break; + case EOpPreIncrement: preString = "(++"; break; + case EOpPreDecrement: preString = "(--"; break; + + case EOpRadians: + preString = "radians("; + break; + case EOpDegrees: + preString = "degrees("; + break; + case EOpSin: + preString = "sin("; + break; + case EOpCos: + preString = "cos("; + break; + case EOpTan: + preString = "tan("; + break; + case EOpAsin: + preString = "asin("; + break; + case EOpAcos: + preString = "acos("; + break; + case EOpAtan: + preString = "atan("; + break; + + case EOpExp: + preString = "exp("; + break; + case EOpLog: + preString = "log("; + break; + case EOpExp2: + preString = "exp2("; + break; + case EOpLog2: + preString = "log2("; + break; + case EOpSqrt: + preString = "sqrt("; + break; + case EOpInverseSqrt: + preString = "inversesqrt("; + break; + + case EOpAbs: + preString = "abs("; + break; + case EOpSign: + preString = "sign("; + break; + case EOpFloor: + preString = "floor("; + break; + case EOpCeil: + preString = "ceil("; + break; + case EOpFract: + preString = "fract("; + break; + + case EOpLength: + preString = "length("; + break; + case EOpNormalize: + preString = "normalize("; + break; + + case EOpDFdx: + preString = "dFdx("; + break; + case EOpDFdy: + preString = "dFdy("; + break; + case EOpFwidth: + preString = "fwidth("; + break; + + case EOpAny: + preString = "any("; + break; + case EOpAll: + preString = "all("; + break; + + default: + UNREACHABLE(); } if (visit == PreVisit && node->getUseEmulatedFunction()) @@ -411,9 +497,9 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node) return true; } -bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection* node) +bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection *node) { - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); if (node->usesTernaryOperator()) { @@ -448,202 +534,270 @@ bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection* node) return false; } -bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) +bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) { bool visitChildren = true; - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); TString preString; - bool delayedWrite = false; + bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction()); switch (node->getOp()) { - case EOpSequence: { - // Scope the sequences except when at the global scope. - if (depth > 0) out << "{\n"; - - incrementDepth(node); - const TIntermSequence& sequence = node->getSequence(); - for (TIntermSequence::const_iterator iter = sequence.begin(); - iter != sequence.end(); ++iter) - { - TIntermNode* node = *iter; - ASSERT(node != NULL); - node->traverse(this); + case EOpSequence: + // Scope the sequences except when at the global scope. + if (mDepth > 0) + { + out << "{\n"; + } - if (isSingleStatement(node)) - out << ";\n"; - } - decrementDepth(); + incrementDepth(node); + for (TIntermSequence::const_iterator iter = node->getSequence()->begin(); + iter != node->getSequence()->end(); ++iter) + { + TIntermNode *node = *iter; + ASSERT(node != NULL); + node->traverse(this); - // Scope the sequences except when at the global scope. - if (depth > 0) out << "}\n"; - visitChildren = false; - break; + if (isSingleStatement(node)) + out << ";\n"; } - case EOpPrototype: { - // Function declaration. - ASSERT(visit == PreVisit); - writeVariableType(node->getType()); - out << " " << hashName(node->getName()); - - out << "("; - writeFunctionParameters(node->getSequence()); - out << ")"; + decrementDepth(); - visitChildren = false; - break; - } - case EOpFunction: { - // Function definition. - ASSERT(visit == PreVisit); - writeVariableType(node->getType()); - out << " " << hashFunctionName(node->getName()); - - incrementDepth(node); - // Function definition node contains one or two children nodes - // representing function parameters and function body. The latter - // is not present in case of empty function bodies. - const TIntermSequence& sequence = node->getSequence(); - ASSERT((sequence.size() == 1) || (sequence.size() == 2)); - TIntermSequence::const_iterator seqIter = sequence.begin(); - - // Traverse function parameters. - TIntermAggregate* params = (*seqIter)->getAsAggregate(); - ASSERT(params != NULL); - ASSERT(params->getOp() == EOpParameters); - params->traverse(this); - - // Traverse function body. - TIntermAggregate* body = ++seqIter != sequence.end() ? - (*seqIter)->getAsAggregate() : NULL; - visitCodeBlock(body); - decrementDepth(); - - // Fully processed; no need to visit children. - visitChildren = false; - break; + // Scope the sequences except when at the global scope. + if (mDepth > 0) + { + out << "}\n"; } - case EOpFunctionCall: - // Function call. - if (visit == PreVisit) - { - out << hashFunctionName(node->getName()) << "("; - } - else if (visit == InVisit) - { - out << ", "; - } - else - { - out << ")"; - } - break; - case EOpParameters: { - // Function parameters. - ASSERT(visit == PreVisit); - out << "("; - writeFunctionParameters(node->getSequence()); + visitChildren = false; + break; + case EOpPrototype: + // Function declaration. + ASSERT(visit == PreVisit); + writeVariableType(node->getType()); + out << " " << hashName(node->getName()); + + out << "("; + writeFunctionParameters(*(node->getSequence())); + out << ")"; + + visitChildren = false; + break; + case EOpFunction: { + // Function definition. + ASSERT(visit == PreVisit); + writeVariableType(node->getType()); + out << " " << hashFunctionName(node->getName()); + + incrementDepth(node); + // Function definition node contains one or two children nodes + // representing function parameters and function body. The latter + // is not present in case of empty function bodies. + const TIntermSequence &sequence = *(node->getSequence()); + ASSERT((sequence.size() == 1) || (sequence.size() == 2)); + TIntermSequence::const_iterator seqIter = sequence.begin(); + + // Traverse function parameters. + TIntermAggregate *params = (*seqIter)->getAsAggregate(); + ASSERT(params != NULL); + ASSERT(params->getOp() == EOpParameters); + params->traverse(this); + + // Traverse function body. + TIntermAggregate *body = ++seqIter != sequence.end() ? + (*seqIter)->getAsAggregate() : NULL; + visitCodeBlock(body); + decrementDepth(); + + // Fully processed; no need to visit children. + visitChildren = false; + break; + } + case EOpFunctionCall: + // Function call. + if (visit == PreVisit) + out << hashFunctionName(node->getName()) << "("; + else if (visit == InVisit) + out << ", "; + else out << ")"; - visitChildren = false; - break; + break; + case EOpParameters: + // Function parameters. + ASSERT(visit == PreVisit); + out << "("; + writeFunctionParameters(*(node->getSequence())); + out << ")"; + visitChildren = false; + break; + case EOpDeclaration: + // Variable declaration. + if (visit == PreVisit) + { + const TIntermSequence &sequence = *(node->getSequence()); + const TIntermTyped *variable = sequence.front()->getAsTyped(); + writeVariableType(variable->getType()); + out << " "; + mDeclaringVariables = true; } - case EOpDeclaration: { - // Variable declaration. - if (visit == PreVisit) - { - const TIntermSequence& sequence = node->getSequence(); - const TIntermTyped* variable = sequence.front()->getAsTyped(); - writeVariableType(variable->getType()); - out << " "; - mDeclaringVariables = true; - } - else if (visit == InVisit) - { - out << ", "; - mDeclaringVariables = true; - } - else - { - mDeclaringVariables = false; - } - break; + else if (visit == InVisit) + { + out << ", "; + mDeclaringVariables = true; } - case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break; - case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break; - case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break; - case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break; - case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break; - case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break; - case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break; - case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break; - case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break; - case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break; - case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break; - case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break; - case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break; - case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break; - case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break; - case EOpConstructStruct: - if (visit == PreVisit) - { - const TType& type = node->getType(); - ASSERT(type.getBasicType() == EbtStruct); - out << hashName(type.getStruct()->name()) << "("; - } - else if (visit == InVisit) - { - out << ", "; - } - else - { - out << ")"; - } - break; - - case EOpLessThan: preString = "lessThan("; delayedWrite = true; break; - case EOpGreaterThan: preString = "greaterThan("; delayedWrite = true; break; - case EOpLessThanEqual: preString = "lessThanEqual("; delayedWrite = true; break; - case EOpGreaterThanEqual: preString = "greaterThanEqual("; delayedWrite = true; break; - case EOpVectorEqual: preString = "equal("; delayedWrite = true; break; - case EOpVectorNotEqual: preString = "notEqual("; delayedWrite = true; break; - case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break; - - case EOpMod: preString = "mod("; delayedWrite = true; break; - case EOpPow: preString = "pow("; delayedWrite = true; break; - case EOpAtan: preString = "atan("; delayedWrite = true; break; - case EOpMin: preString = "min("; delayedWrite = true; break; - case EOpMax: preString = "max("; delayedWrite = true; break; - case EOpClamp: preString = "clamp("; delayedWrite = true; break; - case EOpMix: preString = "mix("; delayedWrite = true; break; - case EOpStep: preString = "step("; delayedWrite = true; break; - case EOpSmoothStep: preString = "smoothstep("; delayedWrite = true; break; - - case EOpDistance: preString = "distance("; delayedWrite = true; break; - case EOpDot: preString = "dot("; delayedWrite = true; break; - case EOpCross: preString = "cross("; delayedWrite = true; break; - case EOpFaceForward: preString = "faceforward("; delayedWrite = true; break; - case EOpReflect: preString = "reflect("; delayedWrite = true; break; - case EOpRefract: preString = "refract("; delayedWrite = true; break; - case EOpMul: preString = "matrixCompMult("; delayedWrite = true; break; - - default: UNREACHABLE(); break; + else + { + mDeclaringVariables = false; + } + break; + case EOpConstructFloat: + writeTriplet(visit, "float(", NULL, ")"); + break; + case EOpConstructVec2: + writeBuiltInFunctionTriplet(visit, "vec2(", false); + break; + case EOpConstructVec3: + writeBuiltInFunctionTriplet(visit, "vec3(", false); + break; + case EOpConstructVec4: + writeBuiltInFunctionTriplet(visit, "vec4(", false); + break; + case EOpConstructBool: + writeTriplet(visit, "bool(", NULL, ")"); + break; + case EOpConstructBVec2: + writeBuiltInFunctionTriplet(visit, "bvec2(", false); + break; + case EOpConstructBVec3: + writeBuiltInFunctionTriplet(visit, "bvec3(", false); + break; + case EOpConstructBVec4: + writeBuiltInFunctionTriplet(visit, "bvec4(", false); + break; + case EOpConstructInt: + writeTriplet(visit, "int(", NULL, ")"); + break; + case EOpConstructIVec2: + writeBuiltInFunctionTriplet(visit, "ivec2(", false); + break; + case EOpConstructIVec3: + writeBuiltInFunctionTriplet(visit, "ivec3(", false); + break; + case EOpConstructIVec4: + writeBuiltInFunctionTriplet(visit, "ivec4(", false); + break; + case EOpConstructMat2: + writeBuiltInFunctionTriplet(visit, "mat2(", false); + break; + case EOpConstructMat3: + writeBuiltInFunctionTriplet(visit, "mat3(", false); + break; + case EOpConstructMat4: + writeBuiltInFunctionTriplet(visit, "mat4(", false); + break; + case EOpConstructStruct: + if (visit == PreVisit) + { + const TType &type = node->getType(); + ASSERT(type.getBasicType() == EbtStruct); + out << hashName(type.getStruct()->name()) << "("; + } + else if (visit == InVisit) + { + out << ", "; + } + else + { + out << ")"; + } + break; + + case EOpLessThan: + writeBuiltInFunctionTriplet(visit, "lessThan(", useEmulatedFunction); + break; + case EOpGreaterThan: + writeBuiltInFunctionTriplet(visit, "greaterThan(", useEmulatedFunction); + break; + case EOpLessThanEqual: + writeBuiltInFunctionTriplet(visit, "lessThanEqual(", useEmulatedFunction); + break; + case EOpGreaterThanEqual: + writeBuiltInFunctionTriplet(visit, "greaterThanEqual(", useEmulatedFunction); + break; + case EOpVectorEqual: + writeBuiltInFunctionTriplet(visit, "equal(", useEmulatedFunction); + break; + case EOpVectorNotEqual: + writeBuiltInFunctionTriplet(visit, "notEqual(", useEmulatedFunction); + break; + case EOpComma: + writeTriplet(visit, NULL, ", ", NULL); + break; + + case EOpMod: + writeBuiltInFunctionTriplet(visit, "mod(", useEmulatedFunction); + break; + case EOpPow: + writeBuiltInFunctionTriplet(visit, "pow(", useEmulatedFunction); + break; + case EOpAtan: + writeBuiltInFunctionTriplet(visit, "atan(", useEmulatedFunction); + break; + case EOpMin: + writeBuiltInFunctionTriplet(visit, "min(", useEmulatedFunction); + break; + case EOpMax: + writeBuiltInFunctionTriplet(visit, "max(", useEmulatedFunction); + break; + case EOpClamp: + writeBuiltInFunctionTriplet(visit, "clamp(", useEmulatedFunction); + break; + case EOpMix: + writeBuiltInFunctionTriplet(visit, "mix(", useEmulatedFunction); + break; + case EOpStep: + writeBuiltInFunctionTriplet(visit, "step(", useEmulatedFunction); + break; + case EOpSmoothStep: + writeBuiltInFunctionTriplet(visit, "smoothstep(", useEmulatedFunction); + break; + case EOpDistance: + writeBuiltInFunctionTriplet(visit, "distance(", useEmulatedFunction); + break; + case EOpDot: + writeBuiltInFunctionTriplet(visit, "dot(", useEmulatedFunction); + break; + case EOpCross: + writeBuiltInFunctionTriplet(visit, "cross(", useEmulatedFunction); + break; + case EOpFaceForward: + writeBuiltInFunctionTriplet(visit, "faceforward(", useEmulatedFunction); + break; + case EOpReflect: + writeBuiltInFunctionTriplet(visit, "reflect(", useEmulatedFunction); + break; + case EOpRefract: + writeBuiltInFunctionTriplet(visit, "refract(", useEmulatedFunction); + break; + case EOpMul: + writeBuiltInFunctionTriplet(visit, "matrixCompMult(", useEmulatedFunction); + break; + + default: + UNREACHABLE(); } - if (delayedWrite && visit == PreVisit && node->getUseEmulatedFunction()) - preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString); - if (delayedWrite) - writeTriplet(visit, preString.c_str(), ", ", ")"); return visitChildren; } -bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node) +bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node) { - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); incrementDepth(node); // Loop header. TLoopType loopType = node->getType(); if (loopType == ELoopFor) // for loop { - if (!node->getUnrollFlag()) { + if (!node->getUnrollFlag()) + { out << "for ("; if (node->getInit()) node->getInit()->traverse(this); @@ -657,6 +811,18 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node) node->getExpression()->traverse(this); out << ")\n"; } + else + { + // Need to put a one-iteration loop here to handle break. + TIntermSequence *declSeq = + node->getInit()->getAsAggregate()->getSequence(); + TIntermSymbol *indexSymbol = + (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode(); + TString name = hashVariableName(indexSymbol->getSymbol()); + out << "for (int " << name << " = 0; " + << name << " < 1; " + << "++" << name << ")\n"; + } } else if (loopType == ELoopWhile) // while loop { @@ -674,15 +840,15 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node) // Loop body. if (node->getUnrollFlag()) { - TLoopIndexInfo indexInfo; - mLoopUnroll.FillLoopIndexInfo(node, indexInfo); - mLoopUnroll.Push(indexInfo); - while (mLoopUnroll.SatisfiesLoopCondition()) + out << "{\n"; + mLoopUnrollStack.push(node); + while (mLoopUnrollStack.satisfiesLoopCondition()) { visitCodeBlock(node->getBody()); - mLoopUnroll.Step(); + mLoopUnrollStack.step(); } - mLoopUnroll.Pop(); + mLoopUnrollStack.pop(); + out << "}\n"; } else { @@ -704,21 +870,31 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node) return false; } -bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch* node) +bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch *node) { switch (node->getFlowOp()) { - case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break; - case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break; - case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break; - case EOpReturn: writeTriplet(visit, "return ", NULL, NULL); break; - default: UNREACHABLE(); break; + case EOpKill: + writeTriplet(visit, "discard", NULL, NULL); + break; + case EOpBreak: + writeTriplet(visit, "break", NULL, NULL); + break; + case EOpContinue: + writeTriplet(visit, "continue", NULL, NULL); + break; + case EOpReturn: + writeTriplet(visit, "return ", NULL, NULL); + break; + default: + UNREACHABLE(); } return true; } -void TOutputGLSLBase::visitCodeBlock(TIntermNode* node) { +void TOutputGLSLBase::visitCodeBlock(TIntermNode *node) +{ TInfoSinkBase &out = objSink(); if (node != NULL) { @@ -734,7 +910,7 @@ void TOutputGLSLBase::visitCodeBlock(TIntermNode* node) { } } -TString TOutputGLSLBase::getTypeName(const TType& type) +TString TOutputGLSLBase::getTypeName(const TType &type) { TInfoSinkBase out; if (type.isMatrix()) @@ -746,10 +922,17 @@ TString TOutputGLSLBase::getTypeName(const TType& type) { switch (type.getBasicType()) { - case EbtFloat: out << "vec"; break; - case EbtInt: out << "ivec"; break; - case EbtBool: out << "bvec"; break; - default: UNREACHABLE(); break; + case EbtFloat: + out << "vec"; + break; + case EbtInt: + out << "ivec"; + break; + case EbtBool: + out << "bvec"; + break; + default: + UNREACHABLE(); } out << type.getNominalSize(); } @@ -763,7 +946,7 @@ TString TOutputGLSLBase::getTypeName(const TType& type) return TString(out.c_str()); } -TString TOutputGLSLBase::hashName(const TString& name) +TString TOutputGLSLBase::hashName(const TString &name) { if (mHashFunction == NULL || name.empty()) return name; @@ -775,35 +958,41 @@ TString TOutputGLSLBase::hashName(const TString& name) return hashedName; } -TString TOutputGLSLBase::hashVariableName(const TString& name) +TString TOutputGLSLBase::hashVariableName(const TString &name) { - if (mSymbolTable.findBuiltIn(name) != NULL) + if (mSymbolTable.findBuiltIn(name, mShaderVersion) != NULL) return name; return hashName(name); } -TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name) +TString TOutputGLSLBase::hashFunctionName(const TString &mangled_name) { TString name = TFunction::unmangleName(mangled_name); - if (mSymbolTable.findBuiltIn(mangled_name) != NULL || name == "main") - return name; + if (mSymbolTable.findBuiltIn(mangled_name, mShaderVersion) != NULL || name == "main") + return translateTextureFunction(name); return hashName(name); } -bool TOutputGLSLBase::structDeclared(const TStructure* structure) const +bool TOutputGLSLBase::structDeclared(const TStructure *structure) const { - return mDeclaredStructs.find(structure->name()) != mDeclaredStructs.end(); + ASSERT(structure); + if (structure->name().empty()) + { + return false; + } + + return (mDeclaredStructs.count(structure->uniqueId()) > 0); } -void TOutputGLSLBase::declareStruct(const TStructure* structure) +void TOutputGLSLBase::declareStruct(const TStructure *structure) { - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); out << "struct " << hashName(structure->name()) << "{\n"; - const TFieldList& fields = structure->fields(); + const TFieldList &fields = structure->fields(); for (size_t i = 0; i < fields.size(); ++i) { - const TField* field = fields[i]; + const TField *field = fields[i]; if (writeVariablePrecision(field->type()->getPrecision())) out << " "; out << getTypeName(*field->type()) << " " << hashName(field->name()); @@ -812,6 +1001,5 @@ void TOutputGLSLBase::declareStruct(const TStructure* structure) out << ";\n"; } out << "}"; - - mDeclaredStructs.insert(structure->name()); } + diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h index 76bec4de61..42364de6f5 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -9,71 +9,75 @@ #include -#include "compiler/translator/ForLoopUnroll.h" #include "compiler/translator/intermediate.h" +#include "compiler/translator/LoopInfo.h" #include "compiler/translator/ParseContext.h" class TOutputGLSLBase : public TIntermTraverser { -public: - TOutputGLSLBase(TInfoSinkBase& objSink, + public: + TOutputGLSLBase(TInfoSinkBase &objSink, ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, - NameMap& nameMap, - TSymbolTable& symbolTable); - -protected: - TInfoSinkBase& objSink() { return mObjSink; } - void writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr); - void writeVariableType(const TType& type); + NameMap &nameMap, + TSymbolTable& symbolTable, + int shaderVersion); + + protected: + TInfoSinkBase &objSink() { return mObjSink; } + void writeTriplet(Visit visit, const char *preStr, const char *inStr, const char *postStr); + void writeVariableType(const TType &type); virtual bool writeVariablePrecision(TPrecision precision) = 0; - void writeFunctionParameters(const TIntermSequence& args); - const ConstantUnion* writeConstantUnion(const TType& type, const ConstantUnion* pConstUnion); - TString getTypeName(const TType& type); - - virtual void visitSymbol(TIntermSymbol* node); - virtual void visitConstantUnion(TIntermConstantUnion* node); - virtual bool visitBinary(Visit visit, TIntermBinary* node); - virtual bool visitUnary(Visit visit, TIntermUnary* node); - virtual bool visitSelection(Visit visit, TIntermSelection* node); - virtual bool visitAggregate(Visit visit, TIntermAggregate* node); - virtual bool visitLoop(Visit visit, TIntermLoop* node); - virtual bool visitBranch(Visit visit, TIntermBranch* node); + void writeFunctionParameters(const TIntermSequence &args); + const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *pConstUnion); + TString getTypeName(const TType &type); - void visitCodeBlock(TIntermNode* node); + virtual void visitSymbol(TIntermSymbol *node); + virtual void visitConstantUnion(TIntermConstantUnion *node); + virtual bool visitBinary(Visit visit, TIntermBinary *node); + virtual bool visitUnary(Visit visit, TIntermUnary *node); + virtual bool visitSelection(Visit visit, TIntermSelection *node); + virtual bool visitAggregate(Visit visit, TIntermAggregate *node); + virtual bool visitLoop(Visit visit, TIntermLoop *node); + virtual bool visitBranch(Visit visit, TIntermBranch *node); + void visitCodeBlock(TIntermNode *node); // Return the original name if hash function pointer is NULL; // otherwise return the hashed name. - TString hashName(const TString& name); + TString hashName(const TString &name); // Same as hashName(), but without hashing built-in variables. - TString hashVariableName(const TString& name); + TString hashVariableName(const TString &name); // Same as hashName(), but without hashing built-in functions. - TString hashFunctionName(const TString& mangled_name); + TString hashFunctionName(const TString &mangled_name); + // Used to translate function names for differences between ESSL and GLSL + virtual TString translateTextureFunction(TString &name) { return name; } -private: - bool structDeclared(const TStructure* structure) const; - void declareStruct(const TStructure* structure); + private: + bool structDeclared(const TStructure *structure) const; + void declareStruct(const TStructure *structure); - TInfoSinkBase& mObjSink; + void writeBuiltInFunctionTriplet(Visit visit, const char *preStr, bool useEmulatedFunction); + + TInfoSinkBase &mObjSink; bool mDeclaringVariables; - // Structs are declared as the tree is traversed. This set contains all - // the structs already declared. It is maintained so that a struct is - // declared only once. - typedef std::set DeclaredStructs; - DeclaredStructs mDeclaredStructs; + // This set contains all the ids of the structs from every scope. + std::set mDeclaredStructs; - ForLoopUnroll mLoopUnroll; + // Stack of loops that need to be unrolled. + TLoopStack mLoopUnrollStack; ShArrayIndexClampingStrategy mClampingStrategy; // name hashing. ShHashFunction64 mHashFunction; - NameMap& mNameMap; + NameMap &mNameMap; + + TSymbolTable &mSymbolTable; - TSymbolTable& mSymbolTable; + const int mShaderVersion; }; #endif // CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp index af996df719..1bf1181af0 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2013 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. // @@ -7,13 +7,20 @@ #include "compiler/translator/OutputHLSL.h" #include "common/angleutils.h" +#include "common/utilities.h" +#include "common/blocklayout.h" #include "compiler/translator/compilerdebug.h" -#include "compiler/translator/DetectDiscontinuity.h" #include "compiler/translator/InfoSink.h" +#include "compiler/translator/DetectDiscontinuity.h" #include "compiler/translator/SearchSymbol.h" #include "compiler/translator/UnfoldShortCircuit.h" +#include "compiler/translator/FlagStd140Structs.h" #include "compiler/translator/NodeSearch.h" #include "compiler/translator/RewriteElseBlocks.h" +#include "compiler/translator/UtilsHLSL.h" +#include "compiler/translator/util.h" +#include "compiler/translator/UniformHLSL.h" +#include "compiler/translator/StructureHLSL.h" #include #include @@ -22,27 +29,76 @@ namespace sh { +TString OutputHLSL::TextureFunction::name() const +{ + TString name = "gl_texture"; + + if (IsSampler2D(sampler)) + { + name += "2D"; + } + else if (IsSampler3D(sampler)) + { + name += "3D"; + } + else if (IsSamplerCube(sampler)) + { + name += "Cube"; + } + else UNREACHABLE(); + + if (proj) + { + name += "Proj"; + } + + if (offset) + { + name += "Offset"; + } + + switch(method) + { + case IMPLICIT: break; + case BIAS: break; // Extra parameter makes the signature unique + case LOD: name += "Lod"; break; + case LOD0: name += "Lod0"; break; + case LOD0BIAS: name += "Lod0"; break; // Extra parameter makes the signature unique + case SIZE: name += "Size"; break; + case FETCH: name += "Fetch"; break; + case GRAD: name += "Grad"; break; + default: UNREACHABLE(); + } + + return name + "("; +} + +bool OutputHLSL::TextureFunction::operator<(const TextureFunction &rhs) const +{ + if (sampler < rhs.sampler) return true; + if (sampler > rhs.sampler) return false; + + if (coords < rhs.coords) return true; + if (coords > rhs.coords) return false; + + if (!proj && rhs.proj) return true; + if (proj && !rhs.proj) return false; + + if (!offset && rhs.offset) return true; + if (offset && !rhs.offset) return false; + + if (method < rhs.method) return true; + if (method > rhs.method) return false; + + return false; +} + OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resources, ShShaderOutput outputType) : TIntermTraverser(true, true, true), mContext(context), mOutputType(outputType) { mUnfoldShortCircuit = new UnfoldShortCircuit(context, this); mInsideFunction = false; - mUsesTexture2D = false; - mUsesTexture2D_bias = false; - mUsesTexture2DProj = false; - mUsesTexture2DProj_bias = false; - mUsesTexture2DProjLod = false; - mUsesTexture2DLod = false; - mUsesTextureCube = false; - mUsesTextureCube_bias = false; - mUsesTextureCubeLod = false; - mUsesTexture2DLod0 = false; - mUsesTexture2DLod0_bias = false; - mUsesTexture2DProjLod0 = false; - mUsesTexture2DProjLod0_bias = false; - mUsesTextureCubeLod0 = false; - mUsesTextureCubeLod0_bias = false; mUsesFragColor = false; mUsesFragData = false; mUsesDepthRange = false; @@ -68,50 +124,56 @@ OutputHLSL::OutputHLSL(TParseContext &context, const ShBuiltInResources& resourc mUsesAtan2_3 = false; mUsesAtan2_4 = false; mUsesDiscardRewriting = false; + mUsesNestedBreak = false; mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1; - mScopeDepth = 0; - mUniqueIndex = 0; mContainsLoopDiscontinuity = false; mOutputLod0Function = false; mInsideDiscontinuousLoop = false; + mNestedLoopDepth = 0; mExcessiveLoopIndex = NULL; + mStructureHLSL = new StructureHLSL; + mUniformHLSL = new UniformHLSL(mStructureHLSL, mOutputType); + if (mOutputType == SH_HLSL9_OUTPUT) { - if (mContext.shaderType == SH_FRAGMENT_SHADER) + if (mContext.shaderType == GL_FRAGMENT_SHADER) { - mUniformRegister = 3; // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront + // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront + mUniformHLSL->reserveUniformRegisters(3); } else { - mUniformRegister = 2; // Reserve registers for dx_DepthRange and dx_ViewAdjust + // Reserve registers for dx_DepthRange and dx_ViewAdjust + mUniformHLSL->reserveUniformRegisters(2); } } - else - { - mUniformRegister = 0; - } - mSamplerRegister = 0; + // Reserve registers for the default uniform block and driver constants + mUniformHLSL->reserveInterfaceBlockRegisters(2); } OutputHLSL::~OutputHLSL() { - delete mUnfoldShortCircuit; + SafeDelete(mUnfoldShortCircuit); + SafeDelete(mStructureHLSL); + SafeDelete(mUniformHLSL); } void OutputHLSL::output() { - mContainsLoopDiscontinuity = mContext.shaderType == SH_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot); + mContainsLoopDiscontinuity = mContext.shaderType == GL_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot); + const std::vector &flaggedStructs = FlagStd140ValueStructs(mContext.treeRoot); + makeFlaggedStructMaps(flaggedStructs); // Work around D3D9 bug that would manifest in vertex shaders with selection blocks which // use a vertex attribute as a condition, and some related computation in the else block. - if (mOutputType == SH_HLSL9_OUTPUT && mContext.shaderType == SH_VERTEX_SHADER) + if (mOutputType == SH_HLSL9_OUTPUT && mContext.shaderType == GL_VERTEX_SHADER) { RewriteElseBlocks(mContext.treeRoot); } @@ -123,72 +185,147 @@ void OutputHLSL::output() mContext.infoSink().obj << mBody.c_str(); } +void OutputHLSL::makeFlaggedStructMaps(const std::vector &flaggedStructs) +{ + for (unsigned int structIndex = 0; structIndex < flaggedStructs.size(); structIndex++) + { + TIntermTyped *flaggedNode = flaggedStructs[structIndex]; + + // This will mark the necessary block elements as referenced + flaggedNode->traverse(this); + TString structName(mBody.c_str()); + mBody.erase(); + + mFlaggedStructOriginalNames[flaggedNode] = structName; + + for (size_t pos = structName.find('.'); pos != std::string::npos; pos = structName.find('.')) + { + structName.erase(pos, 1); + } + + mFlaggedStructMappedNames[flaggedNode] = "map" + structName; + } +} + TInfoSinkBase &OutputHLSL::getBodyStream() { return mBody; } -const ActiveUniforms &OutputHLSL::getUniforms() +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 mActiveUniforms; + return mUniformHLSL->getInterfaceBlockRegisterMap(); +} + +const std::map &OutputHLSL::getUniformRegisterMap() const +{ + return mUniformHLSL->getUniformRegisterMap(); } int OutputHLSL::vectorSize(const TType &type) const { - int elementSize = type.isMatrix() ? type.getNominalSize() : 1; + int elementSize = type.isMatrix() ? type.getCols() : 1; int arraySize = type.isArray() ? type.getArraySize() : 1; return elementSize * arraySize; } -void OutputHLSL::header() +TString OutputHLSL::structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName) { - ShShaderType shaderType = mContext.shaderType; - TInfoSinkBase &out = mHeader; + TString init; + + TString preIndentString; + TString fullIndentString; - for (StructDeclarations::iterator structDeclaration = mStructDeclarations.begin(); structDeclaration != mStructDeclarations.end(); structDeclaration++) + for (int spaces = 0; spaces < (indent * 4); spaces++) { - out << *structDeclaration; + preIndentString += ' '; } - for (Constructors::iterator constructor = mConstructors.begin(); constructor != mConstructors.end(); constructor++) + for (int spaces = 0; spaces < ((indent+1) * 4); spaces++) { - out << *constructor; + fullIndentString += ' '; } - TString uniforms; - TString varyings; - TString attributes; + init += preIndentString + "{\n"; - for (ReferencedSymbols::const_iterator uniform = mReferencedUniforms.begin(); uniform != mReferencedUniforms.end(); uniform++) + const TFieldList &fields = structure.fields(); + for (unsigned int fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) { - const TType &type = uniform->second->getType(); - const TString &name = uniform->second->getSymbol(); + const TField &field = *fields[fieldIndex]; + const TString &fieldName = rhsStructName + "." + Decorate(field.name()); + const TType &fieldType = *field.type(); - if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) // Also declare the texture + if (fieldType.getStruct()) { - int index = samplerRegister(mReferencedUniforms[name]); - - uniforms += "uniform SamplerState sampler_" + decorateUniform(name, type) + arrayString(type) + - " : register(s" + str(index) + ");\n"; - - uniforms += "uniform " + textureString(type) + " texture_" + decorateUniform(name, type) + arrayString(type) + - " : register(t" + str(index) + ");\n"; + init += structInitializerString(indent + 1, *fieldType.getStruct(), fieldName); } else { - uniforms += "uniform " + typeString(type) + " " + decorateUniform(name, type) + arrayString(type) + - " : register(" + registerString(mReferencedUniforms[name]) + ");\n"; + init += fullIndentString + fieldName + ",\n"; } } + init += preIndentString + "}" + (indent == 0 ? ";" : ",") + "\n"; + + return init; +} + +void OutputHLSL::header() +{ + TInfoSinkBase &out = mHeader; + + TString varyings; + TString attributes; + TString flaggedStructs; + + for (std::map::const_iterator flaggedStructIt = mFlaggedStructMappedNames.begin(); flaggedStructIt != mFlaggedStructMappedNames.end(); flaggedStructIt++) + { + TIntermTyped *structNode = flaggedStructIt->first; + const TString &mappedName = flaggedStructIt->second; + const TStructure &structure = *structNode->getType().getStruct(); + const TString &originalName = mFlaggedStructOriginalNames[structNode]; + + flaggedStructs += "static " + Decorate(structure.name()) + " " + mappedName + " =\n"; + flaggedStructs += structInitializerString(0, structure, originalName); + flaggedStructs += "\n"; + } + for (ReferencedSymbols::const_iterator varying = mReferencedVaryings.begin(); varying != mReferencedVaryings.end(); varying++) { const TType &type = varying->second->getType(); const TString &name = varying->second->getSymbol(); // Program linking depends on this exact format - varyings += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; + 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++) @@ -196,36 +333,71 @@ void OutputHLSL::header() const TType &type = attribute->second->getType(); const TString &name = attribute->second->getSymbol(); - attributes += "static " + typeString(type) + " " + decorate(name) + arrayString(type) + " = " + initializer(type) + ";\n"; + 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(); + + out << mUniformHLSL->uniformsHeader(mOutputType, mReferencedUniforms); + out << mUniformHLSL->interfaceBlocksHeader(mReferencedInterfaceBlocks); + if (mUsesDiscardRewriting) { out << "#define ANGLE_USES_DISCARD_REWRITING" << "\n"; } - if (shaderType == SH_FRAGMENT_SHADER) + if (mUsesNestedBreak) + { + out << "#define ANGLE_USES_NESTED_BREAK" << "\n"; + } + + if (mContext.shaderType == GL_FRAGMENT_SHADER) { TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers"); const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire)); - const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1; - out << "// Varyings\n"; out << varyings; - out << "\n" - "static float4 gl_Color[" << numColorValues << "] =\n" - "{\n"; - for (unsigned int i = 0; i < numColorValues; i++) + out << "\n"; + + if (mContext.getShaderVersion() >= 300) { - out << " float4(0, 0, 0, 0)"; - if (i + 1 != numColorValues) + for (ReferencedSymbols::const_iterator outputVariableIt = mReferencedOutputVariables.begin(); outputVariableIt != mReferencedOutputVariables.end(); outputVariableIt++) { - out << ","; + 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); } - out << "\n"; } - out << "};\n"; + else + { + const unsigned int numColorValues = usingMRTExtension ? mNumRenderTargets : 1; + + out << "static float4 gl_Color[" << numColorValues << "] =\n" + "{\n"; + for (unsigned int i = 0; i < numColorValues; i++) + { + out << " float4(0, 0, 0, 0)"; + if (i + 1 != numColorValues) + { + out << ","; + } + out << "\n"; + } + + out << "};\n"; + } if (mUsesFragDepth) { @@ -307,523 +479,713 @@ void OutputHLSL::header() out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" "\n"; } - - out << uniforms; + + if (!flaggedStructs.empty()) + { + out << "// Std140 Structures accessed by value\n"; + out << "\n"; + out << flaggedStructs; + out << "\n"; + } + + if (usingMRTExtension && mNumRenderTargets > 1) + { + out << "#define GL_USES_MRT\n"; + } + + if (mUsesFragColor) + { + out << "#define GL_USES_FRAG_COLOR\n"; + } + + if (mUsesFragData) + { + out << "#define GL_USES_FRAG_DATA\n"; + } + } + else // Vertex shader + { + out << "// Attributes\n"; + out << attributes; + out << "\n" + "static float4 gl_Position = float4(0, 0, 0, 0);\n"; + + if (mUsesPointSize) + { + out << "static float gl_PointSize = float(1);\n"; + } + + out << "\n" + "// Varyings\n"; + out << varyings; out << "\n"; - if (mUsesTexture2D) + if (mUsesDepthRange) { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2D(sampler2D s, float2 t)\n" - "{\n" - " return tex2D(s, t);\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n" - "{\n" - " return t.Sample(s, uv);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); + out << "struct gl_DepthRangeParameters\n" + "{\n" + " float near;\n" + " float far;\n" + " float diff;\n" + "};\n" + "\n"; } - if (mUsesTexture2D_bias) + if (mOutputType == SH_HLSL11_OUTPUT) { - if (mOutputType == SH_HLSL9_OUTPUT) + if (mUsesDepthRange) { - out << "float4 gl_texture2D(sampler2D s, float2 t, float bias)\n" + out << "cbuffer DriverConstants : register(b1)\n" "{\n" - " return tex2Dbias(s, float4(t.x, t.y, 0, bias));\n" - "}\n" + " float3 dx_DepthRange : packoffset(c0);\n" + "};\n" "\n"; } - else if (mOutputType == SH_HLSL11_OUTPUT) + } + else + { + if (mUsesDepthRange) { - out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv, float bias)\n" - "{\n" - " return t.SampleBias(s, uv, bias);\n" - "}\n" - "\n"; + out << "uniform float3 dx_DepthRange : register(c0);\n"; } - else UNREACHABLE(); + + out << "uniform float4 dx_ViewAdjust : register(c1);\n" + "\n"; } - if (mUsesTexture2DProj) + if (mUsesDepthRange) { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" - "{\n" - " return tex2Dproj(s, float4(t.x, t.y, 0, t.z));\n" - "}\n" - "\n" - "float4 gl_texture2DProj(sampler2D s, float4 t)\n" - "{\n" - " return tex2Dproj(s, t);\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n" - "{\n" - " return t.Sample(s, float2(uvw.x / uvw.z, uvw.y / uvw.z));\n" - "}\n" - "\n" - "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n" - "{\n" - " return t.Sample(s, float2(uvw.x / uvw.w, uvw.y / uvw.w));\n" - "}\n" - "\n"; - } - else UNREACHABLE(); + out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" + "\n"; } - if (mUsesTexture2DProj_bias) + if (!flaggedStructs.empty()) { - if (mOutputType == SH_HLSL9_OUTPUT) + out << "// Std140 Structures accessed by value\n"; + out << "\n"; + out << flaggedStructs; + out << "\n"; + } + } + + for (TextureFunctionSet::const_iterator textureFunction = mUsesTexture.begin(); textureFunction != mUsesTexture.end(); textureFunction++) + { + // Return type + if (textureFunction->method == TextureFunction::SIZE) + { + switch(textureFunction->sampler) { - out << "float4 gl_texture2DProj(sampler2D s, float3 t, float bias)\n" - "{\n" - " return tex2Dbias(s, float4(t.x / t.z, t.y / t.z, 0, bias));\n" - "}\n" - "\n" - "float4 gl_texture2DProj(sampler2D s, float4 t, float bias)\n" - "{\n" - " return tex2Dbias(s, float4(t.x / t.w, t.y / t.w, 0, bias));\n" - "}\n" - "\n"; + case EbtSampler2D: out << "int2 "; break; + case EbtSampler3D: out << "int3 "; break; + case EbtSamplerCube: out << "int2 "; break; + case EbtSampler2DArray: out << "int3 "; break; + case EbtISampler2D: out << "int2 "; break; + case EbtISampler3D: out << "int3 "; break; + case EbtISamplerCube: out << "int2 "; break; + case EbtISampler2DArray: out << "int3 "; break; + case EbtUSampler2D: out << "int2 "; break; + case EbtUSampler3D: out << "int3 "; break; + case EbtUSamplerCube: out << "int2 "; break; + case EbtUSampler2DArray: out << "int3 "; break; + case EbtSampler2DShadow: out << "int2 "; break; + case EbtSamplerCubeShadow: out << "int2 "; break; + case EbtSampler2DArrayShadow: out << "int3 "; break; + default: UNREACHABLE(); } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw, float bias)\n" - "{\n" - " return t.SampleBias(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), bias);\n" - "}\n" - "\n" - "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw, float bias)\n" - "{\n" - " return t.SampleBias(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), bias);\n" - "}\n" - "\n"; + } + else // Sampling function + { + switch(textureFunction->sampler) + { + case EbtSampler2D: out << "float4 "; break; + case EbtSampler3D: out << "float4 "; break; + case EbtSamplerCube: out << "float4 "; break; + case EbtSampler2DArray: out << "float4 "; break; + case EbtISampler2D: out << "int4 "; break; + case EbtISampler3D: out << "int4 "; break; + case EbtISamplerCube: out << "int4 "; break; + case EbtISampler2DArray: out << "int4 "; break; + case EbtUSampler2D: out << "uint4 "; break; + case EbtUSampler3D: out << "uint4 "; break; + case EbtUSamplerCube: out << "uint4 "; break; + case EbtUSampler2DArray: out << "uint4 "; break; + case EbtSampler2DShadow: out << "float "; break; + case EbtSamplerCubeShadow: out << "float "; break; + case EbtSampler2DArrayShadow: out << "float "; break; + default: UNREACHABLE(); } - else UNREACHABLE(); } - if (mUsesTextureCube) + // Function name + out << textureFunction->name(); + + // Argument list + int hlslCoords = 4; + + if (mOutputType == SH_HLSL9_OUTPUT) { - if (mOutputType == SH_HLSL9_OUTPUT) + switch(textureFunction->sampler) { - out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" - "{\n" - " return texCUBE(s, t);\n" - "}\n" - "\n"; + case EbtSampler2D: out << "sampler2D s"; hlslCoords = 2; break; + case EbtSamplerCube: out << "samplerCUBE s"; hlslCoords = 3; break; + default: UNREACHABLE(); } - else if (mOutputType == SH_HLSL11_OUTPUT) + + switch(textureFunction->method) { - out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n" - "{\n" - " return t.Sample(s, uvw);\n" - "}\n" - "\n"; + case TextureFunction::IMPLICIT: break; + case TextureFunction::BIAS: hlslCoords = 4; break; + case TextureFunction::LOD: hlslCoords = 4; break; + case TextureFunction::LOD0: hlslCoords = 4; break; + case TextureFunction::LOD0BIAS: hlslCoords = 4; break; + default: UNREACHABLE(); + } + } + else if (mOutputType == SH_HLSL11_OUTPUT) + { + switch(textureFunction->sampler) + { + case EbtSampler2D: out << "Texture2D x, SamplerState s"; hlslCoords = 2; break; + case EbtSampler3D: out << "Texture3D x, SamplerState s"; hlslCoords = 3; break; + case EbtSamplerCube: out << "TextureCube x, SamplerState s"; hlslCoords = 3; break; + case EbtSampler2DArray: out << "Texture2DArray x, SamplerState s"; hlslCoords = 3; break; + case EbtISampler2D: out << "Texture2D x, SamplerState s"; hlslCoords = 2; break; + case EbtISampler3D: out << "Texture3D x, SamplerState s"; hlslCoords = 3; break; + case EbtISamplerCube: out << "Texture2DArray x, SamplerState s"; hlslCoords = 3; break; + case EbtISampler2DArray: out << "Texture2DArray x, SamplerState s"; hlslCoords = 3; break; + case EbtUSampler2D: out << "Texture2D x, SamplerState s"; hlslCoords = 2; break; + case EbtUSampler3D: out << "Texture3D x, SamplerState s"; hlslCoords = 3; break; + case EbtUSamplerCube: out << "Texture2DArray x, SamplerState s"; hlslCoords = 3; break; + case EbtUSampler2DArray: out << "Texture2DArray x, SamplerState s"; hlslCoords = 3; break; + case EbtSampler2DShadow: out << "Texture2D x, SamplerComparisonState s"; hlslCoords = 2; break; + case EbtSamplerCubeShadow: out << "TextureCube x, SamplerComparisonState s"; hlslCoords = 3; break; + case EbtSampler2DArrayShadow: out << "Texture2DArray x, SamplerComparisonState s"; hlslCoords = 3; break; + default: UNREACHABLE(); } - else UNREACHABLE(); } + else UNREACHABLE(); - if (mUsesTextureCube_bias) + if (textureFunction->method == TextureFunction::FETCH) // Integer coordinates { - if (mOutputType == SH_HLSL9_OUTPUT) + switch(textureFunction->coords) { - out << "float4 gl_textureCube(samplerCUBE s, float3 t, float bias)\n" - "{\n" - " return texCUBEbias(s, float4(t.x, t.y, t.z, bias));\n" - "}\n" - "\n"; + case 2: out << ", int2 t"; break; + case 3: out << ", int3 t"; break; + default: UNREACHABLE(); } - else if (mOutputType == SH_HLSL11_OUTPUT) + } + else // Floating-point coordinates (except textureSize) + { + switch(textureFunction->coords) { - out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw, float bias)\n" - "{\n" - " return t.SampleBias(s, uvw, bias);\n" - "}\n" - "\n"; + case 1: out << ", int lod"; break; // textureSize() + case 2: out << ", float2 t"; break; + case 3: out << ", float3 t"; break; + case 4: out << ", float4 t"; break; + default: UNREACHABLE(); } - else UNREACHABLE(); } - // These *Lod0 intrinsics are not available in GL fragment shaders. - // They are used to sample using discontinuous texture coordinates. - if (mUsesTexture2DLod0) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2DLod0(sampler2D s, float2 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" - "}\n" - "\n"; + if (textureFunction->method == TextureFunction::GRAD) + { + switch(textureFunction->sampler) + { + case EbtSampler2D: + case EbtISampler2D: + case EbtUSampler2D: + case EbtSampler2DArray: + case EbtISampler2DArray: + case EbtUSampler2DArray: + case EbtSampler2DShadow: + case EbtSampler2DArrayShadow: + out << ", float2 ddx, float2 ddy"; + break; + case EbtSampler3D: + case EbtISampler3D: + case EbtUSampler3D: + case EbtSamplerCube: + case EbtISamplerCube: + case EbtUSamplerCube: + case EbtSamplerCubeShadow: + out << ", float3 ddx, float3 ddy"; + break; + default: UNREACHABLE(); } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv)\n" - "{\n" - " return t.SampleLevel(s, uv, 0);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); } - if (mUsesTexture2DLod0_bias) + switch(textureFunction->method) { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2DLod0(sampler2D s, float2 t, float bias)\n" - "{\n" - " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2DLod0(Texture2D t, SamplerState s, float2 uv, float bias)\n" - "{\n" - " return t.SampleLevel(s, uv, 0);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); + case TextureFunction::IMPLICIT: break; + case TextureFunction::BIAS: break; // Comes after the offset parameter + case TextureFunction::LOD: out << ", float lod"; break; + case TextureFunction::LOD0: break; + case TextureFunction::LOD0BIAS: break; // Comes after the offset parameter + case TextureFunction::SIZE: break; + case TextureFunction::FETCH: out << ", int mip"; break; + case TextureFunction::GRAD: break; + default: UNREACHABLE(); } - if (mUsesTexture2DProjLod0) + if (textureFunction->offset) { - if (mOutputType == SH_HLSL9_OUTPUT) + switch(textureFunction->sampler) { - out << "float4 gl_texture2DProjLod0(sampler2D s, float3 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod(sampler2D s, float4 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float3 uvw)\n" - "{\n" - " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod0(Texture2D t, SamplerState s, float4 uvw)\n" - "{\n" - " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n" - "}\n" - "\n"; + case EbtSampler2D: out << ", int2 offset"; break; + case EbtSampler3D: out << ", int3 offset"; break; + case EbtSampler2DArray: out << ", int2 offset"; break; + case EbtISampler2D: out << ", int2 offset"; break; + case EbtISampler3D: out << ", int3 offset"; break; + case EbtISampler2DArray: out << ", int2 offset"; break; + case EbtUSampler2D: out << ", int2 offset"; break; + case EbtUSampler3D: out << ", int3 offset"; break; + case EbtUSampler2DArray: out << ", int2 offset"; break; + case EbtSampler2DShadow: out << ", int2 offset"; break; + case EbtSampler2DArrayShadow: out << ", int2 offset"; break; + default: UNREACHABLE(); } - else UNREACHABLE(); } - if (mUsesTexture2DProjLod0_bias) + if (textureFunction->method == TextureFunction::BIAS || + textureFunction->method == TextureFunction::LOD0BIAS) { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2DProjLod0_bias(sampler2D s, float3 t, float bias)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod_bias(sampler2D s, float4 t, float bias)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float3 uvw, float bias)\n" - "{\n" - " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod_bias(Texture2D t, SamplerState s, float4 uvw, float bias)\n" - "{\n" - " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); + out << ", float bias"; } - if (mUsesTextureCubeLod0) + out << ")\n" + "{\n"; + + if (textureFunction->method == TextureFunction::SIZE) { - if (mOutputType == SH_HLSL9_OUTPUT) + if (IsSampler2D(textureFunction->sampler) || IsSamplerCube(textureFunction->sampler)) { - out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t)\n" - "{\n" - " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" - "}\n" - "\n"; + if (IsSamplerArray(textureFunction->sampler)) + { + out << " uint width; uint height; uint layers; uint numberOfLevels;\n" + " x.GetDimensions(lod, width, height, layers, numberOfLevels);\n"; + } + else + { + out << " uint width; uint height; uint numberOfLevels;\n" + " x.GetDimensions(lod, width, height, numberOfLevels);\n"; + } } - else if (mOutputType == SH_HLSL11_OUTPUT) + else if (IsSampler3D(textureFunction->sampler)) { - out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw)\n" - "{\n" - " return t.SampleLevel(s, uvw, 0);\n" - "}\n" - "\n"; + out << " uint width; uint height; uint depth; uint numberOfLevels;\n" + " x.GetDimensions(lod, width, height, depth, numberOfLevels);\n"; } else UNREACHABLE(); - } - if (mUsesTextureCubeLod0_bias) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_textureCubeLod0(samplerCUBE s, float3 t, float bias)\n" - "{\n" - " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_textureCubeLod0(TextureCube t, SamplerState s, float3 uvw, float bias)\n" - "{\n" - " return t.SampleLevel(s, uvw, 0);\n" - "}\n" - "\n"; + switch(textureFunction->sampler) + { + case EbtSampler2D: out << " return int2(width, height);"; break; + case EbtSampler3D: out << " return int3(width, height, depth);"; break; + case EbtSamplerCube: out << " return int2(width, height);"; break; + case EbtSampler2DArray: out << " return int3(width, height, layers);"; break; + case EbtISampler2D: out << " return int2(width, height);"; break; + case EbtISampler3D: out << " return int3(width, height, depth);"; break; + case EbtISamplerCube: out << " return int2(width, height);"; break; + case EbtISampler2DArray: out << " return int3(width, height, layers);"; break; + case EbtUSampler2D: out << " return int2(width, height);"; break; + case EbtUSampler3D: out << " return int3(width, height, depth);"; break; + case EbtUSamplerCube: out << " return int2(width, height);"; break; + case EbtUSampler2DArray: out << " return int3(width, height, layers);"; break; + case EbtSampler2DShadow: out << " return int2(width, height);"; break; + case EbtSamplerCubeShadow: out << " return int2(width, height);"; break; + case EbtSampler2DArrayShadow: out << " return int3(width, height, layers);"; break; + default: UNREACHABLE(); } - else UNREACHABLE(); } - - if (usingMRTExtension && mNumRenderTargets > 1) + else { - out << "#define GL_USES_MRT\n"; - } + if (IsIntegerSampler(textureFunction->sampler) && IsSamplerCube(textureFunction->sampler)) + { + out << " float width; float height; float layers; float levels;\n"; - if (mUsesFragColor) - { - out << "#define GL_USES_FRAG_COLOR\n"; - } + out << " uint mip = 0;\n"; - if (mUsesFragData) - { - out << "#define GL_USES_FRAG_DATA\n"; - } - } - else // Vertex shader - { - out << "// Attributes\n"; - out << attributes; - out << "\n" - "static float4 gl_Position = float4(0, 0, 0, 0);\n"; - - if (mUsesPointSize) - { - out << "static float gl_PointSize = float(1);\n"; - } + out << " x.GetDimensions(mip, width, height, layers, levels);\n"; - out << "\n" - "// Varyings\n"; - out << varyings; - out << "\n"; + out << " bool xMajor = abs(t.x) > abs(t.y) && abs(t.x) > abs(t.z);\n"; + out << " bool yMajor = abs(t.y) > abs(t.z) && abs(t.y) > abs(t.x);\n"; + out << " bool zMajor = abs(t.z) > abs(t.x) && abs(t.z) > abs(t.y);\n"; + out << " bool negative = (xMajor && t.x < 0.0f) || (yMajor && t.y < 0.0f) || (zMajor && t.z < 0.0f);\n"; - if (mUsesDepthRange) - { - out << "struct gl_DepthRangeParameters\n" - "{\n" - " float near;\n" - " float far;\n" - " float diff;\n" - "};\n" - "\n"; - } + // FACE_POSITIVE_X = 000b + // FACE_NEGATIVE_X = 001b + // FACE_POSITIVE_Y = 010b + // FACE_NEGATIVE_Y = 011b + // FACE_POSITIVE_Z = 100b + // FACE_NEGATIVE_Z = 101b + out << " int face = (int)negative + (int)yMajor * 2 + (int)zMajor * 4;\n"; - if (mOutputType == SH_HLSL11_OUTPUT) - { - if (mUsesDepthRange) - { - out << "cbuffer DriverConstants : register(b1)\n" - "{\n" - " float3 dx_DepthRange : packoffset(c0);\n" - "};\n" - "\n"; + out << " float u = xMajor ? -t.z : (yMajor && t.y < 0.0f ? -t.x : t.x);\n"; + out << " float v = yMajor ? t.z : (negative ? t.y : -t.y);\n"; + out << " float m = xMajor ? t.x : (yMajor ? t.y : t.z);\n"; + + out << " t.x = (u * 0.5f / m) + 0.5f;\n"; + out << " t.y = (v * 0.5f / m) + 0.5f;\n"; } - } - else - { - if (mUsesDepthRange) + else if (IsIntegerSampler(textureFunction->sampler) && + textureFunction->method != TextureFunction::FETCH) { - out << "uniform float3 dx_DepthRange : register(c0);\n"; - } + if (IsSampler2D(textureFunction->sampler)) + { + if (IsSamplerArray(textureFunction->sampler)) + { + out << " float width; float height; float layers; float levels;\n"; - out << "uniform float4 dx_ViewAdjust : register(c1);\n" - "\n"; - } + if (textureFunction->method == TextureFunction::LOD0) + { + out << " uint mip = 0;\n"; + } + else if (textureFunction->method == TextureFunction::LOD0BIAS) + { + out << " uint mip = bias;\n"; + } + else + { + if (textureFunction->method == TextureFunction::IMPLICIT || + textureFunction->method == TextureFunction::BIAS) + { + out << " x.GetDimensions(0, width, height, layers, levels);\n" + " float2 tSized = float2(t.x * width, t.y * height);\n" + " float dx = length(ddx(tSized));\n" + " float dy = length(ddy(tSized));\n" + " float lod = log2(max(dx, dy));\n"; + + if (textureFunction->method == TextureFunction::BIAS) + { + out << " lod += bias;\n"; + } + } + else if (textureFunction->method == TextureFunction::GRAD) + { + out << " x.GetDimensions(0, width, height, layers, levels);\n" + " float lod = log2(max(length(ddx), length(ddy)));\n"; + } + + out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n"; + } - if (mUsesDepthRange) - { - out << "static gl_DepthRangeParameters gl_DepthRange = {dx_DepthRange.x, dx_DepthRange.y, dx_DepthRange.z};\n" - "\n"; - } + out << " x.GetDimensions(mip, width, height, layers, levels);\n"; + } + else + { + out << " float width; float height; float levels;\n"; - out << uniforms; - out << "\n"; - - if (mUsesTexture2D) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2D(sampler2D s, float2 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x, t.y, 0, 0));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2D(Texture2D t, SamplerState s, float2 uv)\n" - "{\n" - " return t.SampleLevel(s, uv, 0);\n" - "}\n" - "\n"; - } - else UNREACHABLE(); - } + if (textureFunction->method == TextureFunction::LOD0) + { + out << " uint mip = 0;\n"; + } + else if (textureFunction->method == TextureFunction::LOD0BIAS) + { + out << " uint mip = bias;\n"; + } + else + { + if (textureFunction->method == TextureFunction::IMPLICIT || + textureFunction->method == TextureFunction::BIAS) + { + out << " x.GetDimensions(0, width, height, levels);\n" + " float2 tSized = float2(t.x * width, t.y * height);\n" + " float dx = length(ddx(tSized));\n" + " float dy = length(ddy(tSized));\n" + " float lod = log2(max(dx, dy));\n"; + + if (textureFunction->method == TextureFunction::BIAS) + { + out << " lod += bias;\n"; + } + } + else if (textureFunction->method == TextureFunction::LOD) + { + out << " x.GetDimensions(0, width, height, levels);\n"; + } + else if (textureFunction->method == TextureFunction::GRAD) + { + out << " x.GetDimensions(0, width, height, levels);\n" + " float lod = log2(max(length(ddx), length(ddy)));\n"; + } + + out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n"; + } - if (mUsesTexture2DLod) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_texture2DLod(sampler2D s, float2 t, float lod)\n" - "{\n" - " return tex2Dlod(s, float4(t.x, t.y, 0, lod));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) - { - out << "float4 gl_texture2DLod(Texture2D t, SamplerState s, float2 uv, float lod)\n" - "{\n" - " return t.SampleLevel(s, uv, lod);\n" - "}\n" - "\n"; + out << " x.GetDimensions(mip, width, height, levels);\n"; + } + } + else if (IsSampler3D(textureFunction->sampler)) + { + out << " float width; float height; float depth; float levels;\n"; + + if (textureFunction->method == TextureFunction::LOD0) + { + out << " uint mip = 0;\n"; + } + else if (textureFunction->method == TextureFunction::LOD0BIAS) + { + out << " uint mip = bias;\n"; + } + else + { + if (textureFunction->method == TextureFunction::IMPLICIT || + textureFunction->method == TextureFunction::BIAS) + { + out << " x.GetDimensions(0, width, height, depth, levels);\n" + " float3 tSized = float3(t.x * width, t.y * height, t.z * depth);\n" + " float dx = length(ddx(tSized));\n" + " float dy = length(ddy(tSized));\n" + " float lod = log2(max(dx, dy));\n"; + + if (textureFunction->method == TextureFunction::BIAS) + { + out << " lod += bias;\n"; + } + } + else if (textureFunction->method == TextureFunction::GRAD) + { + out << " x.GetDimensions(0, width, height, depth, levels);\n" + " float lod = log2(max(length(ddx), length(ddy)));\n"; + } + + out << " uint mip = uint(min(max(round(lod), 0), levels - 1));\n"; + } + + out << " x.GetDimensions(mip, width, height, depth, levels);\n"; + } + else UNREACHABLE(); } - else UNREACHABLE(); - } - if (mUsesTexture2DProj) - { + out << " return "; + + // HLSL intrinsic if (mOutputType == SH_HLSL9_OUTPUT) { - out << "float4 gl_texture2DProj(sampler2D s, float3 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, 0));\n" - "}\n" - "\n" - "float4 gl_texture2DProj(sampler2D s, float4 t)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, 0));\n" - "}\n" - "\n"; + switch(textureFunction->sampler) + { + case EbtSampler2D: out << "tex2D"; break; + case EbtSamplerCube: out << "texCUBE"; break; + default: UNREACHABLE(); + } + + switch(textureFunction->method) + { + case TextureFunction::IMPLICIT: out << "(s, "; break; + case TextureFunction::BIAS: out << "bias(s, "; break; + case TextureFunction::LOD: out << "lod(s, "; break; + case TextureFunction::LOD0: out << "lod(s, "; break; + case TextureFunction::LOD0BIAS: out << "lod(s, "; break; + default: UNREACHABLE(); + } } else if (mOutputType == SH_HLSL11_OUTPUT) { - out << "float4 gl_texture2DProj(Texture2D t, SamplerState s, float3 uvw)\n" - "{\n" - " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), 0);\n" - "}\n" - "\n" - "float4 gl_texture2DProj(Texture2D t, SamplerState s, float4 uvw)\n" - "{\n" - " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), 0);\n" - "}\n" - "\n"; + if (textureFunction->method == TextureFunction::GRAD) + { + if (IsIntegerSampler(textureFunction->sampler)) + { + out << "x.Load("; + } + else if (IsShadowSampler(textureFunction->sampler)) + { + out << "x.SampleCmpLevelZero(s, "; + } + else + { + out << "x.SampleGrad(s, "; + } + } + else if (IsIntegerSampler(textureFunction->sampler) || + textureFunction->method == TextureFunction::FETCH) + { + out << "x.Load("; + } + else if (IsShadowSampler(textureFunction->sampler)) + { + out << "x.SampleCmp(s, "; + } + else + { + switch(textureFunction->method) + { + case TextureFunction::IMPLICIT: out << "x.Sample(s, "; break; + case TextureFunction::BIAS: out << "x.SampleBias(s, "; break; + case TextureFunction::LOD: out << "x.SampleLevel(s, "; break; + case TextureFunction::LOD0: out << "x.SampleLevel(s, "; break; + case TextureFunction::LOD0BIAS: out << "x.SampleLevel(s, "; break; + default: UNREACHABLE(); + } + } } else UNREACHABLE(); - } - if (mUsesTexture2DProjLod) - { - if (mOutputType == SH_HLSL9_OUTPUT) + // Integer sampling requires integer addresses + TString addressx = ""; + TString addressy = ""; + TString addressz = ""; + TString close = ""; + + if (IsIntegerSampler(textureFunction->sampler) || + textureFunction->method == TextureFunction::FETCH) { - out << "float4 gl_texture2DProjLod(sampler2D s, float3 t, float lod)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.z, t.y / t.z, 0, lod));\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod(sampler2D s, float4 t, float lod)\n" - "{\n" - " return tex2Dlod(s, float4(t.x / t.w, t.y / t.w, 0, lod));\n" - "}\n" - "\n"; + switch(hlslCoords) + { + case 2: out << "int3("; break; + case 3: out << "int4("; break; + default: UNREACHABLE(); + } + + // Convert from normalized floating-point to integer + if (textureFunction->method != TextureFunction::FETCH) + { + addressx = "int(floor(width * frac(("; + addressy = "int(floor(height * frac(("; + + if (IsSamplerArray(textureFunction->sampler)) + { + addressz = "int(max(0, min(layers - 1, floor(0.5 + "; + } + else if (IsSamplerCube(textureFunction->sampler)) + { + addressz = "(((("; + } + else + { + addressz = "int(floor(depth * frac(("; + } + + close = "))))"; + } } - else if (mOutputType == SH_HLSL11_OUTPUT) + else { - out << "float4 gl_texture2DProjLod(Texture2D t, SamplerState s, float3 uvw, float lod)\n" - "{\n" - " return t.SampleLevel(s, float2(uvw.x / uvw.z, uvw.y / uvw.z), lod);\n" - "}\n" - "\n" - "float4 gl_texture2DProjLod(Texture2D t, SamplerState s, float4 uvw, float lod)\n" - "{\n" - " return t.SampleLevel(s, float2(uvw.x / uvw.w, uvw.y / uvw.w), lod);\n" - "}\n" - "\n"; + switch(hlslCoords) + { + case 2: out << "float2("; break; + case 3: out << "float3("; break; + case 4: out << "float4("; break; + default: UNREACHABLE(); + } } - else UNREACHABLE(); - } - if (mUsesTextureCube) - { - if (mOutputType == SH_HLSL9_OUTPUT) - { - out << "float4 gl_textureCube(samplerCUBE s, float3 t)\n" - "{\n" - " return texCUBElod(s, float4(t.x, t.y, t.z, 0));\n" - "}\n" - "\n"; - } - else if (mOutputType == SH_HLSL11_OUTPUT) + TString proj = ""; // Only used for projected textures + + if (textureFunction->proj) { - out << "float4 gl_textureCube(TextureCube t, SamplerState s, float3 uvw)\n" - "{\n" - " return t.SampleLevel(s, uvw, 0);\n" - "}\n" - "\n"; + switch(textureFunction->coords) + { + case 3: proj = " / t.z"; break; + case 4: proj = " / t.w"; break; + default: UNREACHABLE(); + } } - else UNREACHABLE(); - } - if (mUsesTextureCubeLod) - { + out << addressx + ("t.x" + proj) + close + ", " + addressy + ("t.y" + proj) + close; + if (mOutputType == SH_HLSL9_OUTPUT) { - out << "float4 gl_textureCubeLod(samplerCUBE s, float3 t, float lod)\n" - "{\n" - " return texCUBElod(s, float4(t.x, t.y, t.z, lod));\n" - "}\n" - "\n"; + if (hlslCoords >= 3) + { + if (textureFunction->coords < 3) + { + out << ", 0"; + } + else + { + out << ", t.z" + proj; + } + } + + if (hlslCoords == 4) + { + switch(textureFunction->method) + { + case TextureFunction::BIAS: out << ", bias"; break; + case TextureFunction::LOD: out << ", lod"; break; + case TextureFunction::LOD0: out << ", 0"; break; + case TextureFunction::LOD0BIAS: out << ", bias"; break; + default: UNREACHABLE(); + } + } + + out << "));\n"; } else if (mOutputType == SH_HLSL11_OUTPUT) { - out << "float4 gl_textureCubeLod(TextureCube t, SamplerState s, float3 uvw, float lod)\n" - "{\n" - " return t.SampleLevel(s, uvw, lod);\n" - "}\n" - "\n"; + if (hlslCoords >= 3) + { + if (IsIntegerSampler(textureFunction->sampler) && IsSamplerCube(textureFunction->sampler)) + { + out << ", face"; + } + else + { + out << ", " + addressz + ("t.z" + proj) + close; + } + } + + if (textureFunction->method == TextureFunction::GRAD) + { + if (IsIntegerSampler(textureFunction->sampler)) + { + out << ", mip)"; + } + else if (IsShadowSampler(textureFunction->sampler)) + { + // Compare value + switch(textureFunction->coords) + { + case 3: out << "), t.z"; break; + case 4: out << "), t.w"; break; + default: UNREACHABLE(); + } + } + else + { + out << "), ddx, ddy"; + } + } + else if (IsIntegerSampler(textureFunction->sampler) || + textureFunction->method == TextureFunction::FETCH) + { + out << ", mip)"; + } + else if (IsShadowSampler(textureFunction->sampler)) + { + // Compare value + switch(textureFunction->coords) + { + case 3: out << "), t.z"; break; + case 4: out << "), t.w"; break; + default: UNREACHABLE(); + } + } + else + { + switch(textureFunction->method) + { + case TextureFunction::IMPLICIT: out << ")"; break; + case TextureFunction::BIAS: out << "), bias"; break; + case TextureFunction::LOD: out << "), lod"; break; + case TextureFunction::LOD0: out << "), 0"; break; + case TextureFunction::LOD0BIAS: out << "), bias"; break; + default: UNREACHABLE(); + } + } + + if (textureFunction->offset) + { + out << ", offset"; + } + + out << ");"; } else UNREACHABLE(); } + + out << "\n" + "}\n" + "\n"; } if (mUsesFragCoord) @@ -891,7 +1253,7 @@ void OutputHLSL::header() "}\n" "\n"; } - + if (mUsesMod3v) { out << "float3 mod(float3 x, float3 y)\n" @@ -1039,66 +1401,89 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) { TInfoSinkBase &out = mBody; - TString name = node->getSymbol(); - - if (name == "gl_FragColor") - { - out << "gl_Color[0]"; - mUsesFragColor = true; - } - else if (name == "gl_FragData") + // Handle accessing std140 structs by value + if (mFlaggedStructMappedNames.count(node) > 0) { - out << "gl_Color"; - mUsesFragData = true; + out << mFlaggedStructMappedNames[node]; + return; } - else if (name == "gl_DepthRange") + + TString name = node->getSymbol(); + + if (name == "gl_DepthRange") { mUsesDepthRange = true; out << name; } - else if (name == "gl_FragCoord") - { - mUsesFragCoord = true; - out << name; - } - else if (name == "gl_PointCoord") - { - mUsesPointCoord = true; - out << name; - } - else if (name == "gl_FrontFacing") - { - mUsesFrontFacing = true; - out << name; - } - else if (name == "gl_PointSize") - { - mUsesPointSize = true; - out << name; - } - else if (name == "gl_FragDepthEXT") - { - mUsesFragDepth = true; - out << "gl_Depth"; - } else { TQualifier qualifier = node->getQualifier(); if (qualifier == EvqUniform) { - mReferencedUniforms[name] = node; - out << decorateUniform(name, node->getType()); + const TType& nodeType = node->getType(); + const TInterfaceBlock* interfaceBlock = nodeType.getInterfaceBlock(); + + if (interfaceBlock) + { + mReferencedInterfaceBlocks[interfaceBlock->name()] = node; + } + else + { + mReferencedUniforms[name] = node; + } + + out << DecorateUniform(name, nodeType); } - else if (qualifier == EvqAttribute) + else if (qualifier == EvqAttribute || qualifier == EvqVertexIn) { mReferencedAttributes[name] = node; - out << decorate(name); + out << Decorate(name); } - else if (qualifier == EvqVaryingOut || qualifier == EvqInvariantVaryingOut || qualifier == EvqVaryingIn || qualifier == EvqInvariantVaryingIn) + else if (IsVarying(qualifier)) { mReferencedVaryings[name] = node; - out << decorate(name); + out << Decorate(name); + } + else if (qualifier == EvqFragmentOut) + { + mReferencedOutputVariables[name] = node; + out << "out_" << name; + } + else if (qualifier == EvqFragColor) + { + out << "gl_Color[0]"; + mUsesFragColor = true; + } + else if (qualifier == EvqFragData) + { + out << "gl_Color"; + mUsesFragData = true; + } + else if (qualifier == EvqFragCoord) + { + mUsesFragCoord = true; + out << name; + } + else if (qualifier == EvqPointCoord) + { + mUsesPointCoord = true; + out << name; + } + else if (qualifier == EvqFrontFacing) + { + mUsesFrontFacing = true; + out << name; + } + else if (qualifier == EvqPointSize) + { + mUsesPointSize = true; + out << name; + } + else if (name == "gl_FragDepthEXT") + { + mUsesFragDepth = true; + out << "gl_Depth"; } else if (qualifier == EvqInternal) { @@ -1106,15 +1491,27 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node) } else { - out << decorate(name); + out << Decorate(name); } } } +void OutputHLSL::visitRaw(TIntermRaw *node) +{ + mBody << node->getRawText(); +} + bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) { TInfoSinkBase &out = mBody; + // Handle accessing std140 structs by value + if (mFlaggedStructMappedNames.count(node) > 0) + { + out << mFlaggedStructMappedNames[node]; + return false; + } + switch (node->getOp()) { case EOpAssign: outputTriplet(visit, "(", " = ", ")"); break; @@ -1165,7 +1562,7 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) { out << " = mul("; node->getLeft()->traverse(this); - out << ", transpose("; + out << ", transpose("; } else { @@ -1181,7 +1578,7 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) { out << " = mul("; node->getLeft()->traverse(this); - out << ", "; + out << ", "; } else { @@ -1189,15 +1586,49 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) } break; case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break; - case EOpIndexDirect: outputTriplet(visit, "", "[", "]"); break; - case EOpIndexIndirect: outputTriplet(visit, "", "[", "]"); break; + case EOpIndexDirect: + { + const TType& leftType = node->getLeft()->getType(); + if (leftType.isInterfaceBlock()) + { + if (visit == PreVisit) + { + TInterfaceBlock* interfaceBlock = leftType.getInterfaceBlock(); + const int arrayIndex = node->getRight()->getAsConstantUnion()->getIConst(0); + mReferencedInterfaceBlocks[interfaceBlock->instanceName()] = node->getLeft()->getAsSymbolNode(); + out << mUniformHLSL->interfaceBlockInstanceString(*interfaceBlock, arrayIndex); + return false; + } + } + else + { + outputTriplet(visit, "", "[", "]"); + } + } + break; + case EOpIndexIndirect: + // We do not currently support indirect references to interface blocks + ASSERT(node->getLeft()->getBasicType() != EbtInterfaceBlock); + outputTriplet(visit, "", "[", "]"); + break; case EOpIndexDirectStruct: if (visit == InVisit) { const TStructure* structure = node->getLeft()->getType().getStruct(); const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion(); const TField* field = structure->fields()[index->getIConst(0)]; - out << "." + decorateField(field->name(), node->getLeft()->getType()); + out << "." + DecorateField(field->name(), *structure); + + return false; + } + break; + case EOpIndexDirectInterfaceBlock: + if (visit == InVisit) + { + const TInterfaceBlock* interfaceBlock = node->getLeft()->getType().getInterfaceBlock(); + const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion(); + const TField* field = interfaceBlock->fields()[index->getIConst(0)]; + out << "." + Decorate(field->name()); return false; } @@ -1211,9 +1642,9 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) if (swizzle) { - TIntermSequence &sequence = swizzle->getSequence(); + TIntermSequence *sequence = swizzle->getSequence(); - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) + for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++) { TIntermConstantUnion *element = (*sit)->getAsConstantUnion(); @@ -1266,16 +1697,17 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) out << "!("; } - const TFieldList &fields = node->getLeft()->getType().getStruct()->fields(); + const TStructure &structure = *node->getLeft()->getType().getStruct(); + const TFieldList &fields = structure.fields(); for (size_t i = 0; i < fields.size(); i++) { const TField *field = fields[i]; node->getLeft()->traverse(this); - out << "." + decorateField(field->name(), node->getLeft()->getType()) + " == "; + out << "." + DecorateField(field->name(), structure) + " == "; node->getRight()->traverse(this); - out << "." + decorateField(field->name(), node->getLeft()->getType()); + out << "." + DecorateField(field->name(), structure); if (i < fields.size() - 1) { @@ -1346,46 +1778,13 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) { switch (node->getOp()) { - case EOpNegative: outputTriplet(visit, "(-", "", ")"); break; - case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break; - case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break; - case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break; - case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break; - case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break; - case EOpPreDecrement: outputTriplet(visit, "(--", "", ")"); break; - case EOpConvIntToBool: - case EOpConvFloatToBool: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: outputTriplet(visit, "bool(", "", ")"); break; - case 2: outputTriplet(visit, "bool2(", "", ")"); break; - case 3: outputTriplet(visit, "bool3(", "", ")"); break; - case 4: outputTriplet(visit, "bool4(", "", ")"); break; - default: UNREACHABLE(); - } - break; - case EOpConvBoolToFloat: - case EOpConvIntToFloat: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: outputTriplet(visit, "float(", "", ")"); break; - case 2: outputTriplet(visit, "float2(", "", ")"); break; - case 3: outputTriplet(visit, "float3(", "", ")"); break; - case 4: outputTriplet(visit, "float4(", "", ")"); break; - default: UNREACHABLE(); - } - break; - case EOpConvFloatToInt: - case EOpConvBoolToInt: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: outputTriplet(visit, "int(", "", ")"); break; - case 2: outputTriplet(visit, "int2(", "", ")"); break; - case 3: outputTriplet(visit, "int3(", "", ")"); break; - case 4: outputTriplet(visit, "int4(", "", ")"); break; - default: UNREACHABLE(); - } - break; + case EOpNegative: outputTriplet(visit, "(-", "", ")"); break; + case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break; + case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break; + case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break; + case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break; + case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break; + case EOpPreDecrement: outputTriplet(visit, "(--", "", ")"); break; case EOpRadians: outputTriplet(visit, "radians(", "", ")"); break; case EOpDegrees: outputTriplet(visit, "degrees(", "", ")"); break; case EOpSin: outputTriplet(visit, "sin(", "", ")"); break; @@ -1457,20 +1856,9 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { outputLineDirective(node->getLine().first_line); out << "{\n"; - - mScopeDepth++; - - if (mScopeBracket.size() < mScopeDepth) - { - mScopeBracket.push_back(0); // New scope level - } - else - { - mScopeBracket[mScopeDepth - 1]++; // New scope at existing level - } } - for (TIntermSequence::iterator sit = node->getSequence().begin(); sit != node->getSequence().end(); sit++) + for (TIntermSequence::iterator sit = node->getSequence()->begin(); sit != node->getSequence()->end(); sit++) { outputLineDirective((*sit)->getLine().first_line); @@ -1483,8 +1871,6 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { outputLineDirective(node->getLine().last_line); out << "}\n"; - - mScopeDepth--; } return false; @@ -1492,14 +1878,16 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpDeclaration: if (visit == PreVisit) { - TIntermSequence &sequence = node->getSequence(); - TIntermTyped *variable = sequence[0]->getAsTyped(); + TIntermSequence *sequence = node->getSequence(); + TIntermTyped *variable = (*sequence)[0]->getAsTyped(); if (variable && (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal)) { - if (variable->getType().getStruct()) + TStructure *structure = variable->getType().getStruct(); + + if (structure) { - addConstructor(variable->getType(), scopedStruct(variable->getType().getStruct()->name()), NULL); + mStructureHLSL->addConstructor(variable->getType(), StructNameString(*structure), NULL); } if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration @@ -1509,16 +1897,16 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) out << "static "; } - out << typeString(variable->getType()) + " "; + out << TypeString(variable->getType()) + " "; - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) + for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++) { TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); if (symbol) { symbol->traverse(this); - out << arrayString(symbol->getType()); + out << ArrayString(symbol->getType()); out << " = " + initializer(symbol->getType()); } else @@ -1526,7 +1914,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) (*sit)->traverse(this); } - if (*sit != sequence.back()) + if (*sit != sequence->back()) { out << ", "; } @@ -1538,9 +1926,9 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) } else UNREACHABLE(); } - else if (variable && (variable->getQualifier() == EvqVaryingOut || variable->getQualifier() == EvqInvariantVaryingOut)) + else if (variable && IsVaryingOut(variable->getQualifier())) { - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); sit++) + for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++) { TIntermSymbol *symbol = (*sit)->getAsSymbolNode(); @@ -1566,19 +1954,19 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpPrototype: if (visit == PreVisit) { - out << typeString(node->getType()) << " " << decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "("); + out << TypeString(node->getType()) << " " << Decorate(node->getName()) << (mOutputLod0Function ? "Lod0(" : "("); - TIntermSequence &arguments = node->getSequence(); + TIntermSequence *arguments = node->getSequence(); - for (unsigned int i = 0; i < arguments.size(); i++) + for (unsigned int i = 0; i < arguments->size(); i++) { - TIntermSymbol *symbol = arguments[i]->getAsSymbolNode(); + TIntermSymbol *symbol = (*arguments)[i]->getAsSymbolNode(); if (symbol) { out << argumentString(symbol); - if (i < arguments.size() - 1) + if (i < arguments->size() - 1) { out << ", "; } @@ -1604,7 +1992,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) { TString name = TFunction::unmangleName(node->getName()); - out << typeString(node->getType()) << " "; + out << TypeString(node->getType()) << " "; if (name == "main") { @@ -1612,26 +2000,28 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) } else { - out << decorate(name) << (mOutputLod0Function ? "Lod0(" : "("); + out << Decorate(name) << (mOutputLod0Function ? "Lod0(" : "("); } - TIntermSequence &sequence = node->getSequence(); - TIntermSequence &arguments = sequence[0]->getAsAggregate()->getSequence(); + TIntermSequence *sequence = node->getSequence(); + TIntermSequence *arguments = (*sequence)[0]->getAsAggregate()->getSequence(); - for (unsigned int i = 0; i < arguments.size(); i++) + for (unsigned int i = 0; i < arguments->size(); i++) { - TIntermSymbol *symbol = arguments[i]->getAsSymbolNode(); + TIntermSymbol *symbol = (*arguments)[i]->getAsSymbolNode(); if (symbol) { - if (symbol->getType().getStruct()) + TStructure *structure = symbol->getType().getStruct(); + + if (structure) { - addConstructor(symbol->getType(), scopedStruct(symbol->getType().getStruct()->name()), NULL); + mStructureHLSL->addConstructor(symbol->getType(), StructNameString(*structure), NULL); } out << argumentString(symbol); - if (i < arguments.size() - 1) + if (i < arguments->size() - 1) { out << ", "; } @@ -1641,169 +2031,160 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) out << ")\n" "{\n"; - - if (sequence.size() > 1) + + if (sequence->size() > 1) { mInsideFunction = true; - sequence[1]->traverse(this); + (*sequence)[1]->traverse(this); mInsideFunction = false; } - + out << "}\n"; if (mContainsLoopDiscontinuity && !mOutputLod0Function) { if (name != "main") { - mOutputLod0Function = true; - node->traverse(this); - mOutputLod0Function = false; + mOutputLod0Function = true; + node->traverse(this); + mOutputLod0Function = false; + } + } + + return false; + } + break; + case EOpFunctionCall: + { + TString name = TFunction::unmangleName(node->getName()); + bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function; + TIntermSequence *arguments = node->getSequence(); + + if (node->isUserDefined()) + { + out << Decorate(name) << (lod0 ? "Lod0(" : "("); + } + else + { + TBasicType samplerType = (*arguments)[0]->getAsTyped()->getType().getBasicType(); + + TextureFunction textureFunction; + textureFunction.sampler = samplerType; + textureFunction.coords = (*arguments)[1]->getAsTyped()->getNominalSize(); + textureFunction.method = TextureFunction::IMPLICIT; + textureFunction.proj = false; + textureFunction.offset = false; + + if (name == "texture2D" || name == "textureCube" || name == "texture") + { + textureFunction.method = TextureFunction::IMPLICIT; + } + else if (name == "texture2DProj" || name == "textureProj") + { + textureFunction.method = TextureFunction::IMPLICIT; + textureFunction.proj = true; + } + else if (name == "texture2DLod" || name == "textureCubeLod" || name == "textureLod" || + name == "texture2DLodEXT" || name == "textureCubeLodEXT") + { + textureFunction.method = TextureFunction::LOD; + } + else if (name == "texture2DProjLod" || name == "textureProjLod" || name == "texture2DProjLodEXT") + { + textureFunction.method = TextureFunction::LOD; + textureFunction.proj = true; + } + else if (name == "textureSize") + { + textureFunction.method = TextureFunction::SIZE; + } + else if (name == "textureOffset") + { + textureFunction.method = TextureFunction::IMPLICIT; + textureFunction.offset = true; + } + else if (name == "textureProjOffset") + { + textureFunction.method = TextureFunction::IMPLICIT; + textureFunction.offset = true; + textureFunction.proj = true; + } + else if (name == "textureLodOffset") + { + textureFunction.method = TextureFunction::LOD; + textureFunction.offset = true; + } + else if (name == "textureProjLodOffset") + { + textureFunction.method = TextureFunction::LOD; + textureFunction.proj = true; + textureFunction.offset = true; + } + else if (name == "texelFetch") + { + textureFunction.method = TextureFunction::FETCH; + } + else if (name == "texelFetchOffset") + { + textureFunction.method = TextureFunction::FETCH; + textureFunction.offset = true; + } + else if (name == "textureGrad" || name == "texture2DGradEXT") + { + textureFunction.method = TextureFunction::GRAD; + } + else if (name == "textureGradOffset") + { + textureFunction.method = TextureFunction::GRAD; + textureFunction.offset = true; } - } - - return false; - } - break; - case EOpFunctionCall: - { - TString name = TFunction::unmangleName(node->getName()); - bool lod0 = mInsideDiscontinuousLoop || mOutputLod0Function; - - if (node->isUserDefined()) - { - out << decorate(name) << (lod0 ? "Lod0(" : "("); - } - else - { - if (name == "texture2D") + else if (name == "textureProjGrad" || name == "texture2DProjGradEXT" || name == "textureCubeGradEXT") { - if (!lod0) - { - if (node->getSequence().size() == 2) - { - mUsesTexture2D = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTexture2D_bias = true; - } - else UNREACHABLE(); - - out << "gl_texture2D("; - } - else - { - if (node->getSequence().size() == 2) - { - mUsesTexture2DLod0 = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTexture2DLod0_bias = true; - } - else UNREACHABLE(); - - out << "gl_texture2DLod0("; - } + textureFunction.method = TextureFunction::GRAD; + textureFunction.proj = true; } - else if (name == "texture2DProj") + else if (name == "textureProjGradOffset") { - if (!lod0) - { - if (node->getSequence().size() == 2) - { - mUsesTexture2DProj = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTexture2DProj_bias = true; - } - else UNREACHABLE(); - - out << "gl_texture2DProj("; - } - else - { - if (node->getSequence().size() == 2) - { - mUsesTexture2DProjLod0 = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTexture2DProjLod0_bias = true; - } - else UNREACHABLE(); - - out << "gl_texture2DProjLod0("; - } + textureFunction.method = TextureFunction::GRAD; + textureFunction.proj = true; + textureFunction.offset = true; } - else if (name == "textureCube") + else UNREACHABLE(); + + if (textureFunction.method == TextureFunction::IMPLICIT) // Could require lod 0 or have a bias argument { - if (!lod0) - { - if (node->getSequence().size() == 2) - { - mUsesTextureCube = true; - } - else if (node->getSequence().size() == 3) - { - mUsesTextureCube_bias = true; - } - else UNREACHABLE(); + unsigned int mandatoryArgumentCount = 2; // All functions have sampler and coordinate arguments - out << "gl_textureCube("; + if (textureFunction.offset) + { + mandatoryArgumentCount++; } - else + + bool bias = (arguments->size() > mandatoryArgumentCount); // Bias argument is optional + + if (lod0 || mContext.shaderType == GL_VERTEX_SHADER) { - if (node->getSequence().size() == 2) + if (bias) { - mUsesTextureCubeLod0 = true; + textureFunction.method = TextureFunction::LOD0BIAS; } - else if (node->getSequence().size() == 3) + else { - mUsesTextureCubeLod0_bias = true; + textureFunction.method = TextureFunction::LOD0; } - else UNREACHABLE(); - - out << "gl_textureCubeLod0("; } - } - else if (name == "texture2DLod") - { - if (node->getSequence().size() == 3) + else if (bias) { - mUsesTexture2DLod = true; + textureFunction.method = TextureFunction::BIAS; } - else UNREACHABLE(); - - out << "gl_texture2DLod("; } - else if (name == "texture2DProjLod") - { - if (node->getSequence().size() == 3) - { - mUsesTexture2DProjLod = true; - } - else UNREACHABLE(); - out << "gl_texture2DProjLod("; - } - else if (name == "textureCubeLod") - { - if (node->getSequence().size() == 3) - { - mUsesTextureCubeLod = true; - } - else UNREACHABLE(); + mUsesTexture.insert(textureFunction); - out << "gl_textureCubeLod("; - } - else UNREACHABLE(); + out << textureFunction.name(); } - TIntermSequence &arguments = node->getSequence(); - - for (TIntermSequence::iterator arg = arguments.begin(); arg != arguments.end(); arg++) + for (TIntermSequence::iterator arg = arguments->begin(); arg != arguments->end(); arg++) { if (mOutputType == SH_HLSL11_OUTPUT && IsSampler((*arg)->getAsTyped()->getBasicType())) { @@ -1814,7 +2195,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) (*arg)->traverse(this); - if (arg < arguments.end() - 1) + if (arg < arguments->end() - 1) { out << ", "; } @@ -1825,70 +2206,32 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) return false; } break; - case EOpParameters: outputTriplet(visit, "(", ", ", ")\n{\n"); break; - case EOpConstructFloat: - addConstructor(node->getType(), "vec1", &node->getSequence()); - outputTriplet(visit, "vec1(", "", ")"); - break; - case EOpConstructVec2: - addConstructor(node->getType(), "vec2", &node->getSequence()); - outputTriplet(visit, "vec2(", ", ", ")"); - break; - case EOpConstructVec3: - addConstructor(node->getType(), "vec3", &node->getSequence()); - outputTriplet(visit, "vec3(", ", ", ")"); - break; - case EOpConstructVec4: - addConstructor(node->getType(), "vec4", &node->getSequence()); - outputTriplet(visit, "vec4(", ", ", ")"); - break; - case EOpConstructBool: - addConstructor(node->getType(), "bvec1", &node->getSequence()); - outputTriplet(visit, "bvec1(", "", ")"); - break; - case EOpConstructBVec2: - addConstructor(node->getType(), "bvec2", &node->getSequence()); - outputTriplet(visit, "bvec2(", ", ", ")"); - break; - case EOpConstructBVec3: - addConstructor(node->getType(), "bvec3", &node->getSequence()); - outputTriplet(visit, "bvec3(", ", ", ")"); - break; - case EOpConstructBVec4: - addConstructor(node->getType(), "bvec4", &node->getSequence()); - outputTriplet(visit, "bvec4(", ", ", ")"); - break; - case EOpConstructInt: - addConstructor(node->getType(), "ivec1", &node->getSequence()); - outputTriplet(visit, "ivec1(", "", ")"); - break; - case EOpConstructIVec2: - addConstructor(node->getType(), "ivec2", &node->getSequence()); - outputTriplet(visit, "ivec2(", ", ", ")"); - break; - case EOpConstructIVec3: - addConstructor(node->getType(), "ivec3", &node->getSequence()); - outputTriplet(visit, "ivec3(", ", ", ")"); - break; - case EOpConstructIVec4: - addConstructor(node->getType(), "ivec4", &node->getSequence()); - outputTriplet(visit, "ivec4(", ", ", ")"); - break; - case EOpConstructMat2: - addConstructor(node->getType(), "mat2", &node->getSequence()); - outputTriplet(visit, "mat2(", ", ", ")"); - break; - case EOpConstructMat3: - addConstructor(node->getType(), "mat3", &node->getSequence()); - outputTriplet(visit, "mat3(", ", ", ")"); - break; - case EOpConstructMat4: - addConstructor(node->getType(), "mat4", &node->getSequence()); - outputTriplet(visit, "mat4(", ", ", ")"); - break; + case EOpParameters: outputTriplet(visit, "(", ", ", ")\n{\n"); break; + case EOpConstructFloat: outputConstructor(visit, node->getType(), "vec1", node->getSequence()); break; + case EOpConstructVec2: outputConstructor(visit, node->getType(), "vec2", node->getSequence()); break; + case EOpConstructVec3: outputConstructor(visit, node->getType(), "vec3", node->getSequence()); break; + case EOpConstructVec4: outputConstructor(visit, node->getType(), "vec4", node->getSequence()); break; + case EOpConstructBool: outputConstructor(visit, node->getType(), "bvec1", node->getSequence()); break; + case EOpConstructBVec2: outputConstructor(visit, node->getType(), "bvec2", node->getSequence()); break; + case EOpConstructBVec3: outputConstructor(visit, node->getType(), "bvec3", node->getSequence()); break; + case EOpConstructBVec4: outputConstructor(visit, node->getType(), "bvec4", node->getSequence()); break; + case EOpConstructInt: outputConstructor(visit, node->getType(), "ivec1", node->getSequence()); break; + case EOpConstructIVec2: outputConstructor(visit, node->getType(), "ivec2", node->getSequence()); break; + case EOpConstructIVec3: outputConstructor(visit, node->getType(), "ivec3", node->getSequence()); break; + case EOpConstructIVec4: outputConstructor(visit, node->getType(), "ivec4", node->getSequence()); break; + case EOpConstructUInt: outputConstructor(visit, node->getType(), "uvec1", node->getSequence()); break; + case EOpConstructUVec2: outputConstructor(visit, node->getType(), "uvec2", node->getSequence()); break; + case EOpConstructUVec3: outputConstructor(visit, node->getType(), "uvec3", node->getSequence()); break; + case EOpConstructUVec4: outputConstructor(visit, node->getType(), "uvec4", node->getSequence()); break; + case EOpConstructMat2: outputConstructor(visit, node->getType(), "mat2", node->getSequence()); break; + case EOpConstructMat3: outputConstructor(visit, node->getType(), "mat3", node->getSequence()); break; + case EOpConstructMat4: outputConstructor(visit, node->getType(), "mat4", node->getSequence()); break; case EOpConstructStruct: - addConstructor(node->getType(), scopedStruct(node->getType().getStruct()->name()), &node->getSequence()); - outputTriplet(visit, structLookup(node->getType().getStruct()->name()) + "_ctor(", ", ", ")"); + { + const TString &structName = StructNameString(*node->getType().getStruct()); + mStructureHLSL->addConstructor(node->getType(), structName, node->getSequence()); + outputTriplet(visit, structName + "_ctor(", ", ", ")"); + } break; case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break; case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break; @@ -1899,8 +2242,9 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpMod: { // We need to look at the number of components in both arguments - switch (node->getSequence()[0]->getAsTyped()->getNominalSize() * 10 - + node->getSequence()[1]->getAsTyped()->getNominalSize()) + const int modValue = (*node->getSequence())[0]->getAsTyped()->getNominalSize() * 10 + + (*node->getSequence())[1]->getAsTyped()->getNominalSize(); + switch (modValue) { case 11: mUsesMod1 = true; break; case 22: mUsesMod2v = true; break; @@ -1917,8 +2261,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) break; case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break; case EOpAtan: - ASSERT(node->getSequence().size() == 2); // atan(x) is a unary operator - switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) + ASSERT(node->getSequence()->size() == 2); // atan(x) is a unary operator + switch ((*node->getSequence())[0]->getAsTyped()->getNominalSize()) { case 1: mUsesAtan2_1 = true; break; case 2: mUsesAtan2_2 = true; break; @@ -1939,7 +2283,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case EOpCross: outputTriplet(visit, "cross(", ", ", ")"); break; case EOpFaceForward: { - switch (node->getSequence()[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument + switch ((*node->getSequence())[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument { case 1: mUsesFaceforward1 = true; break; case 2: mUsesFaceforward2 = true; break; @@ -1947,7 +2291,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) case 4: mUsesFaceforward4 = true; break; default: UNREACHABLE(); } - + outputTriplet(visit, "faceforward(", ", ", ")"); } break; @@ -1977,7 +2321,7 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node) node->getCondition()->traverse(this); out << ")\n"; - + outputLineDirective(node->getLine().first_line); out << "{\n"; @@ -2028,6 +2372,8 @@ void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node) bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) { + mNestedLoopDepth++; + bool wasDiscontinuous = mInsideDiscontinuousLoop; if (mContainsLoopDiscontinuity && !mInsideDiscontinuousLoop) @@ -2039,6 +2385,9 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) { if (handleExcessiveLoop(node)) { + mInsideDiscontinuousLoop = wasDiscontinuous; + mNestedLoopDepth--; + return false; } } @@ -2055,7 +2404,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) else { out << "{for("; - + if (node->getInit()) { node->getInit()->traverse(this); @@ -2076,7 +2425,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) } out << ")\n"; - + outputLineDirective(node->getLine().first_line); out << "{\n"; } @@ -2102,6 +2451,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node) out << "}\n"; mInsideDiscontinuousLoop = wasDiscontinuous; + mNestedLoopDepth--; return false; } @@ -2118,6 +2468,11 @@ bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) case EOpBreak: if (visit == PreVisit) { + if (mNestedLoopDepth > 1) + { + mUsesNestedBreak = true; + } + if (mExcessiveLoopIndex) { out << "{Break"; @@ -2179,7 +2534,7 @@ bool OutputHLSL::isSingleStatement(TIntermNode *node) } else { - for (TIntermSequence::iterator sit = aggregate->getSequence().begin(); sit != aggregate->getSequence().end(); sit++) + for (TIntermSequence::iterator sit = aggregate->getSequence()->begin(); sit != aggregate->getSequence()->end(); sit++) { if (!isSingleStatement(*sit)) { @@ -2216,8 +2571,8 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) if (init) { - TIntermSequence &sequence = init->getSequence(); - TIntermTyped *variable = sequence[0]->getAsTyped(); + TIntermSequence *sequence = init->getSequence(); + TIntermTyped *variable = (*sequence)[0]->getAsTyped(); if (variable && variable->getQualifier() == EvqTemporary) { @@ -2230,7 +2585,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) if (symbol && constant) { - if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) + if (constant->getBasicType() == EbtInt && constant->isScalar()) { index = symbol; initial = constant->getIConst(0); @@ -2245,14 +2600,14 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) if (index != NULL && node->getCondition()) { TIntermBinary *test = node->getCondition()->getAsBinaryNode(); - + if (test && test->getLeft()->getAsSymbolNode()->getId() == index->getId()) { TIntermConstantUnion *constant = test->getRight()->getAsConstantUnion(); if (constant) { - if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) + if (constant->getBasicType() == EbtInt && constant->isScalar()) { comparator = test->getOp(); limit = constant->getIConst(0); @@ -2266,7 +2621,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) { TIntermBinary *binaryTerminal = node->getExpression()->getAsBinaryNode(); TIntermUnary *unaryTerminal = node->getExpression()->getAsUnaryNode(); - + if (binaryTerminal) { TOperator op = binaryTerminal->getOp(); @@ -2274,7 +2629,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) if (constant) { - if (constant->getBasicType() == EbtInt && constant->getNominalSize() == 1) + if (constant->getBasicType() == EbtInt && constant->isScalar()) { int value = constant->getIConst(0); @@ -2346,7 +2701,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) { mExcessiveLoopIndex = NULL; // Stops setting the Break flag } - + // for(int index = initial; index < clampedLimit; index += increment) out << "for("; @@ -2364,7 +2719,7 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) out << " += "; out << increment; out << ")\n"; - + outputLineDirective(node->getLine().first_line); out << "{\n"; @@ -2385,449 +2740,130 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node) initial += MAX_LOOP_ITERATIONS * increment; iterations -= MAX_LOOP_ITERATIONS; - } - - out << "}"; - - mExcessiveLoopIndex = restoreIndex; - - return true; - } - else UNIMPLEMENTED(); - } - - return false; // Not handled as an excessive loop -} - -void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString) -{ - TInfoSinkBase &out = mBody; - - if (visit == PreVisit) - { - out << preString; - } - else if (visit == InVisit) - { - out << inString; - } - else if (visit == PostVisit) - { - out << postString; - } -} - -void OutputHLSL::outputLineDirective(int line) -{ - if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0)) - { - mBody << "\n"; - mBody << "#line " << line; - - if (mContext.sourcePath) - { - mBody << " \"" << mContext.sourcePath << "\""; - } - - mBody << "\n"; - } -} - -TString OutputHLSL::argumentString(const TIntermSymbol *symbol) -{ - TQualifier qualifier = symbol->getQualifier(); - const TType &type = symbol->getType(); - TString name = symbol->getSymbol(); - - if (name.empty()) // HLSL demands named arguments, also for prototypes - { - name = "x" + str(mUniqueIndex++); - } - else - { - name = decorate(name); - } - - if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) - { - return qualifierString(qualifier) + " " + textureString(type) + " texture_" + name + arrayString(type) + ", " + - qualifierString(qualifier) + " SamplerState sampler_" + name + arrayString(type); - } - - return qualifierString(qualifier) + " " + typeString(type) + " " + name + arrayString(type); -} - -TString OutputHLSL::qualifierString(TQualifier qualifier) -{ - switch(qualifier) - { - case EvqIn: return "in"; - case EvqOut: return "out"; - case EvqInOut: return "inout"; - case EvqConstReadOnly: return "const"; - default: UNREACHABLE(); - } - - return ""; -} - -TString OutputHLSL::typeString(const TType &type) -{ - if (type.getBasicType() == EbtStruct) - { - const TString& typeName = type.getStruct()->name(); - if (typeName != "") - { - return structLookup(typeName); - } - else // Nameless structure, define in place - { - const TFieldList &fields = type.getStruct()->fields(); - - TString string = "struct\n" - "{\n"; - - for (unsigned int i = 0; i < fields.size(); i++) - { - const TField *field = fields[i]; - - string += " " + typeString(*field->type()) + " " + decorate(field->name()) + arrayString(*field->type()) + ";\n"; - } - - string += "} "; - - return string; - } - } - else if (type.isMatrix()) - { - switch (type.getNominalSize()) - { - case 2: return "float2x2"; - case 3: return "float3x3"; - case 4: return "float4x4"; - } - } - else - { - switch (type.getBasicType()) - { - case EbtFloat: - switch (type.getNominalSize()) - { - case 1: return "float"; - case 2: return "float2"; - case 3: return "float3"; - case 4: return "float4"; - } - case EbtInt: - switch (type.getNominalSize()) - { - case 1: return "int"; - case 2: return "int2"; - case 3: return "int3"; - case 4: return "int4"; - } - case EbtBool: - switch (type.getNominalSize()) - { - case 1: return "bool"; - case 2: return "bool2"; - case 3: return "bool3"; - case 4: return "bool4"; - } - case EbtVoid: - return "void"; - case EbtSampler2D: - return "sampler2D"; - case EbtSamplerCube: - return "samplerCUBE"; - case EbtSamplerExternalOES: - return "sampler2D"; - default: - break; - } - } - - UNREACHABLE(); - return ""; -} - -TString OutputHLSL::textureString(const TType &type) -{ - switch (type.getBasicType()) - { - case EbtSampler2D: - return "Texture2D"; - case EbtSamplerCube: - return "TextureCube"; - case EbtSamplerExternalOES: - return "Texture2D"; - default: - break; - } - - UNREACHABLE(); - return ""; -} - -TString OutputHLSL::arrayString(const TType &type) -{ - if (!type.isArray()) - { - return ""; - } - - return "[" + str(type.getArraySize()) + "]"; -} - -TString OutputHLSL::initializer(const TType &type) -{ - TString string; - - size_t size = type.getObjectSize(); - for (size_t component = 0; component < size; component++) - { - string += "0"; - - if (component + 1 < size) - { - string += ", "; - } - } - - return "{" + string + "}"; -} - -void OutputHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters) -{ - if (name == "") - { - return; // Nameless structures don't have constructors - } - - if (type.getStruct() && mStructNames.find(decorate(name)) != mStructNames.end()) - { - return; // Already added - } - - TType ctorType = type; - ctorType.clearArrayness(); - ctorType.setPrecision(EbpHigh); - ctorType.setQualifier(EvqTemporary); - - TString ctorName = type.getStruct() ? decorate(name) : name; - - typedef std::vector ParameterArray; - ParameterArray ctorParameters; - - if (type.getStruct()) - { - mStructNames.insert(decorate(name)); - - TString structure; - structure += "struct " + decorate(name) + "\n" - "{\n"; + } - const TFieldList &fields = type.getStruct()->fields(); + out << "}"; - for (unsigned int i = 0; i < fields.size(); i++) - { - const TField *field = fields[i]; + mExcessiveLoopIndex = restoreIndex; - structure += " " + typeString(*field->type()) + " " + decorateField(field->name(), type) + arrayString(*field->type()) + ";\n"; + return true; } + else UNIMPLEMENTED(); + } - structure += "};\n"; + return false; // Not handled as an excessive loop +} - if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structure) == mStructDeclarations.end()) - { - mStructDeclarations.push_back(structure); - } +void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString) +{ + TInfoSinkBase &out = mBody; - for (unsigned int i = 0; i < fields.size(); i++) - { - ctorParameters.push_back(*fields[i]->type()); - } - } - else if (parameters) + if (visit == PreVisit) { - for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++) - { - ctorParameters.push_back((*parameter)->getAsTyped()->getType()); - } + out << preString; } - else UNREACHABLE(); - - TString constructor; - - if (ctorType.getStruct()) + else if (visit == InVisit) { - constructor += ctorName + " " + ctorName + "_ctor("; + out << inString; } - else // Built-in type + else if (visit == PostVisit) { - constructor += typeString(ctorType) + " " + ctorName + "("; + out << postString; } +} - for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++) +void OutputHLSL::outputLineDirective(int line) +{ + if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0)) { - const TType &type = ctorParameters[parameter]; - - constructor += typeString(type) + " x" + str(parameter) + arrayString(type); + mBody << "\n"; + mBody << "#line " << line; - if (parameter < ctorParameters.size() - 1) + if (mContext.sourcePath) { - constructor += ", "; + mBody << " \"" << mContext.sourcePath << "\""; } + + mBody << "\n"; } +} - constructor += ")\n" - "{\n"; +TString OutputHLSL::argumentString(const TIntermSymbol *symbol) +{ + TQualifier qualifier = symbol->getQualifier(); + const TType &type = symbol->getType(); + TString name = symbol->getSymbol(); - if (ctorType.getStruct()) + if (name.empty()) // HLSL demands named arguments, also for prototypes { - constructor += " " + ctorName + " structure = {"; + name = "x" + str(mUniqueIndex++); } else { - constructor += " return " + typeString(ctorType) + "("; + name = Decorate(name); } - if (ctorType.isMatrix() && ctorParameters.size() == 1) + if (mOutputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) { - int dim = ctorType.getNominalSize(); - const TType ¶meter = ctorParameters[0]; + return QualifierString(qualifier) + " " + TextureString(type) + " texture_" + name + ArrayString(type) + ", " + + QualifierString(qualifier) + " " + SamplerString(type) + " sampler_" + name + ArrayString(type); + } - if (parameter.isScalar()) - { - for (int row = 0; row < dim; row++) - { - for (int col = 0; col < dim; col++) - { - constructor += TString((row == col) ? "x0" : "0.0"); - - if (row < dim - 1 || col < dim - 1) - { - constructor += ", "; - } - } - } - } - else if (parameter.isMatrix()) - { - for (int row = 0; row < dim; row++) - { - for (int col = 0; col < dim; col++) - { - if (row < parameter.getNominalSize() && col < parameter.getNominalSize()) - { - constructor += TString("x0") + "[" + str(row) + "]" + "[" + str(col) + "]"; - } - else - { - constructor += TString((row == col) ? "1.0" : "0.0"); - } + return QualifierString(qualifier) + " " + TypeString(type) + " " + name + ArrayString(type); +} - if (row < dim - 1 || col < dim - 1) - { - constructor += ", "; - } - } - } - } - else UNREACHABLE(); - } - else +TString OutputHLSL::initializer(const TType &type) +{ + TString string; + + size_t size = type.getObjectSize(); + for (size_t component = 0; component < size; component++) { - size_t remainingComponents = ctorType.getObjectSize(); - size_t parameterIndex = 0; + string += "0"; - while (remainingComponents > 0) + if (component + 1 < size) { - const TType ¶meter = ctorParameters[parameterIndex]; - const size_t parameterSize = parameter.getObjectSize(); - bool moreParameters = parameterIndex + 1 < ctorParameters.size(); - - constructor += "x" + str(parameterIndex); + string += ", "; + } + } - if (parameter.isScalar()) - { - ASSERT(parameterSize <= remainingComponents); - remainingComponents -= parameterSize; - } - else if (parameter.isVector()) - { - if (remainingComponents == parameterSize || moreParameters) - { - ASSERT(parameterSize <= remainingComponents); - remainingComponents -= parameterSize; - } - else if (remainingComponents < static_cast(parameter.getNominalSize())) - { - switch (remainingComponents) - { - case 1: constructor += ".x"; break; - case 2: constructor += ".xy"; break; - case 3: constructor += ".xyz"; break; - case 4: constructor += ".xyzw"; break; - default: UNREACHABLE(); - } + return "{" + string + "}"; +} - remainingComponents = 0; - } - else UNREACHABLE(); - } - else if (parameter.isMatrix() || parameter.getStruct()) - { - ASSERT(remainingComponents == parameterSize || moreParameters); - ASSERT(parameterSize <= remainingComponents); - - remainingComponents -= parameterSize; - } - else UNREACHABLE(); +void OutputHLSL::outputConstructor(Visit visit, const TType &type, const TString &name, const TIntermSequence *parameters) +{ + TInfoSinkBase &out = mBody; - if (moreParameters) - { - parameterIndex++; - } + if (visit == PreVisit) + { + mStructureHLSL->addConstructor(type, name, parameters); - if (remainingComponents) - { - constructor += ", "; - } - } + out << name + "("; } - - if (ctorType.getStruct()) + else if (visit == InVisit) { - constructor += "};\n" - " return structure;\n" - "}\n"; + out << ", "; } - else + else if (visit == PostVisit) { - constructor += ");\n" - "}\n"; + out << ")"; } - - mConstructors.insert(constructor); } const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion) { TInfoSinkBase &out = mBody; - if (type.getBasicType() == EbtStruct) + const TStructure* structure = type.getStruct(); + if (structure) { - out << structLookup(type.getStruct()->name()) + "_ctor("; - - const TFieldList &fields = type.getStruct()->fields(); + out << StructNameString(*structure) + "_ctor("; + + const TFieldList& fields = structure->fields(); for (size_t i = 0; i < fields.size(); i++) { const TType *fieldType = fields[i]->type(); - constUnion = writeConstantUnion(*fieldType, constUnion); if (i != fields.size() - 1) @@ -2842,10 +2878,10 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con { size_t size = type.getObjectSize(); bool writeType = size > 1; - + if (writeType) { - out << typeString(type) << "("; + out << TypeString(type) << "("; } for (size_t i = 0; i < size; i++, constUnion++) @@ -2854,6 +2890,7 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con { case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, constUnion->getFConst())); break; case EbtInt: out << constUnion->getIConst(); break; + case EbtUInt: out << constUnion->getUConst(); break; case EbtBool: out << constUnion->getBConst(); break; default: UNREACHABLE(); } @@ -2873,266 +2910,29 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con return constUnion; } -TString OutputHLSL::scopeString(unsigned int depthLimit) -{ - TString string; - - for (unsigned int i = 0; i < mScopeBracket.size() && i < depthLimit; i++) - { - string += "_" + str(i); - } - - return string; -} - -TString OutputHLSL::scopedStruct(const TString &typeName) -{ - if (typeName == "") - { - return typeName; - } - - return typeName + scopeString(mScopeDepth); -} - -TString OutputHLSL::structLookup(const TString &typeName) -{ - for (int depth = mScopeDepth; depth >= 0; depth--) - { - TString scopedName = decorate(typeName + scopeString(depth)); - - for (StructNames::iterator structName = mStructNames.begin(); structName != mStructNames.end(); structName++) - { - if (*structName == scopedName) - { - return scopedName; - } - } - } - - UNREACHABLE(); // Should have found a matching constructor - - return typeName; -} - -TString OutputHLSL::decorate(const TString &string) -{ - if (string.compare(0, 3, "gl_") != 0 && string.compare(0, 3, "dx_") != 0) - { - return "_" + string; - } - - return string; -} - -TString OutputHLSL::decorateUniform(const TString &string, const TType &type) -{ - if (type.getBasicType() == EbtSamplerExternalOES) - { - return "ex_" + string; - } - - return decorate(string); -} - -TString OutputHLSL::decorateField(const TString &string, const TType &structure) -{ - if (structure.getStruct()->name().compare(0, 3, "gl_") != 0) - { - return decorate(string); - } - - return string; -} - -TString OutputHLSL::registerString(TIntermSymbol *operand) -{ - ASSERT(operand->getQualifier() == EvqUniform); - - if (IsSampler(operand->getBasicType())) - { - return "s" + str(samplerRegister(operand)); - } - - return "c" + str(uniformRegister(operand)); -} - -int OutputHLSL::samplerRegister(TIntermSymbol *sampler) -{ - const TType &type = sampler->getType(); - ASSERT(IsSampler(type.getBasicType())); - - int index = mSamplerRegister; - mSamplerRegister += sampler->totalRegisterCount(); - - declareUniform(type, sampler->getSymbol(), index); - - return index; -} - -int OutputHLSL::uniformRegister(TIntermSymbol *uniform) -{ - const TType &type = uniform->getType(); - ASSERT(!IsSampler(type.getBasicType())); - - int index = mUniformRegister; - mUniformRegister += uniform->totalRegisterCount(); - - declareUniform(type, uniform->getSymbol(), index); - - return index; -} - -void OutputHLSL::declareUniform(const TType &type, const TString &name, int index) +class DeclareVaryingTraverser : public GetVariableTraverser { - TStructure *structure = type.getStruct(); - - if (!structure) - { - mActiveUniforms.push_back(Uniform(glVariableType(type), glVariablePrecision(type), name.c_str(), type.getArraySize(), index)); - } - else - { - const TFieldList &fields = structure->fields(); - - if (type.isArray()) - { - int elementIndex = index; - - for (int i = 0; i < type.getArraySize(); i++) - { - for (size_t j = 0; j < fields.size(); j++) - { - const TType &fieldType = *fields[j]->type(); - const TString uniformName = name + "[" + str(i) + "]." + fields[j]->name(); - declareUniform(fieldType, uniformName, elementIndex); - elementIndex += fieldType.totalRegisterCount(); - } - } - } - else - { - int fieldIndex = index; - - for (size_t i = 0; i < fields.size(); i++) - { - const TType &fieldType = *fields[i]->type(); - const TString uniformName = name + "." + fields[i]->name(); - declareUniform(fieldType, uniformName, fieldIndex); - fieldIndex += fieldType.totalRegisterCount(); - } - } - } -} + public: + DeclareVaryingTraverser(std::vector *output, + InterpolationType interpolation) + : GetVariableTraverser(output), + mInterpolation(interpolation) + {} -GLenum OutputHLSL::glVariableType(const TType &type) -{ - if (type.getBasicType() == EbtFloat) - { - if (type.isScalar()) - { - return GL_FLOAT; - } - else if (type.isVector()) - { - switch(type.getNominalSize()) - { - case 2: return GL_FLOAT_VEC2; - case 3: return GL_FLOAT_VEC3; - case 4: return GL_FLOAT_VEC4; - default: UNREACHABLE(); - } - } - else if (type.isMatrix()) - { - switch(type.getNominalSize()) - { - case 2: return GL_FLOAT_MAT2; - case 3: return GL_FLOAT_MAT3; - case 4: return GL_FLOAT_MAT4; - default: UNREACHABLE(); - } - } - else UNREACHABLE(); - } - else if (type.getBasicType() == EbtInt) - { - if (type.isScalar()) - { - return GL_INT; - } - else if (type.isVector()) - { - switch(type.getNominalSize()) - { - case 2: return GL_INT_VEC2; - case 3: return GL_INT_VEC3; - case 4: return GL_INT_VEC4; - default: UNREACHABLE(); - } - } - else UNREACHABLE(); - } - else if (type.getBasicType() == EbtBool) - { - if (type.isScalar()) - { - return GL_BOOL; - } - else if (type.isVector()) - { - switch(type.getNominalSize()) - { - case 2: return GL_BOOL_VEC2; - case 3: return GL_BOOL_VEC3; - case 4: return GL_BOOL_VEC4; - default: UNREACHABLE(); - } - } - else UNREACHABLE(); - } - else if (type.getBasicType() == EbtSampler2D) - { - return GL_SAMPLER_2D; - } - else if (type.getBasicType() == EbtSamplerCube) + private: + void visitVariable(Varying *varying) { - return GL_SAMPLER_CUBE; + varying->interpolation = mInterpolation; } - else UNREACHABLE(); - return GL_NONE; -} + InterpolationType mInterpolation; +}; -GLenum OutputHLSL::glVariablePrecision(const TType &type) +void OutputHLSL::declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, + const TString &name, std::vector &fieldsOut) { - if (type.getBasicType() == EbtFloat) - { - switch (type.getPrecision()) - { - case EbpHigh: return GL_HIGH_FLOAT; - case EbpMedium: return GL_MEDIUM_FLOAT; - case EbpLow: return GL_LOW_FLOAT; - case EbpUndefined: - // Should be defined as the default precision by the parser - default: UNREACHABLE(); - } - } - else if (type.getBasicType() == EbtInt) - { - switch (type.getPrecision()) - { - case EbpHigh: return GL_HIGH_INT; - case EbpMedium: return GL_MEDIUM_INT; - case EbpLow: return GL_LOW_INT; - case EbpUndefined: - // Should be defined as the default precision by the parser - default: UNREACHABLE(); - } - } - - // Other types (boolean, sampler) don't have a precision - return GL_NONE; + 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 3afd8e9ada..78bb741a11 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2013 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,16 +11,18 @@ #include #include -#define GL_APICALL -#include - +#include "angle_gl.h" #include "compiler/translator/intermediate.h" #include "compiler/translator/ParseContext.h" -#include "compiler/translator/Uniform.h" +#include "common/shadervars.h" namespace sh { class UnfoldShortCircuit; +class StructureHLSL; +class UniformHLSL; + +typedef std::map ReferencedSymbols; class OutputHLSL : public TIntermTraverser { @@ -31,22 +33,23 @@ class OutputHLSL : public TIntermTraverser void output(); TInfoSinkBase &getBodyStream(); - const ActiveUniforms &getUniforms(); + 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; - TString typeString(const TType &type); - TString textureString(const TType &type); - static TString qualifierString(TQualifier qualifier); - static TString arrayString(const TType &type); static TString initializer(const TType &type); - static TString decorate(const TString &string); // Prepends an underscore to avoid naming clashes - static TString decorateUniform(const TString &string, const TType &type); - static TString decorateField(const TString &string, const TType &structure); protected: void header(); // Visit AST nodes and output their code to the body stream void visitSymbol(TIntermSymbol*); + void visitRaw(TIntermRaw*); void visitConstantUnion(TIntermConstantUnion*); bool visitBinary(Visit visit, TIntermBinary*); bool visitUnary(Visit visit, TIntermUnary*); @@ -63,13 +66,9 @@ class OutputHLSL : public TIntermTraverser TString argumentString(const TIntermSymbol *symbol); int vectorSize(const TType &type) const; - void addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters); + void outputConstructor(Visit visit, const TType &type, const TString &name, const TIntermSequence *parameters); const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion); - TString scopeString(unsigned int depthLimit); - TString scopedStruct(const TString &typeName); - TString structLookup(const TString &typeName); - TParseContext &mContext; const ShShaderOutput mOutputType; UnfoldShortCircuit *mUnfoldShortCircuit; @@ -80,27 +79,44 @@ class OutputHLSL : public TIntermTraverser TInfoSinkBase mBody; TInfoSinkBase mFooter; - typedef std::map ReferencedSymbols; ReferencedSymbols mReferencedUniforms; + ReferencedSymbols mReferencedInterfaceBlocks; ReferencedSymbols mReferencedAttributes; ReferencedSymbols mReferencedVaryings; + ReferencedSymbols mReferencedOutputVariables; + + StructureHLSL *mStructureHLSL; + UniformHLSL *mUniformHLSL; + + struct TextureFunction + { + enum Method + { + IMPLICIT, // Mipmap LOD determined implicitly (standard lookup) + BIAS, + LOD, + LOD0, + LOD0BIAS, + SIZE, // textureSize() + FETCH, + GRAD + }; + + TBasicType sampler; + int coords; + bool proj; + bool offset; + Method method; + + TString name() const; + + bool operator<(const TextureFunction &rhs) const; + }; + + typedef std::set TextureFunctionSet; // Parameters determining what goes in the header output - bool mUsesTexture2D; - bool mUsesTexture2D_bias; - bool mUsesTexture2DLod; - bool mUsesTexture2DProj; - bool mUsesTexture2DProj_bias; - bool mUsesTexture2DProjLod; - bool mUsesTextureCube; - bool mUsesTextureCube_bias; - bool mUsesTextureCubeLod; - bool mUsesTexture2DLod0; - bool mUsesTexture2DLod0_bias; - bool mUsesTexture2DProjLod0; - bool mUsesTexture2DProjLod0_bias; - bool mUsesTextureCubeLod0; - bool mUsesTextureCubeLod0_bias; + TextureFunctionSet mUsesTexture; bool mUsesFragColor; bool mUsesFragData; bool mUsesDepthRange; @@ -126,42 +142,32 @@ class OutputHLSL : public TIntermTraverser bool mUsesAtan2_3; bool mUsesAtan2_4; bool mUsesDiscardRewriting; + bool mUsesNestedBreak; int mNumRenderTargets; - typedef std::set Constructors; - Constructors mConstructors; - - typedef std::set StructNames; - StructNames mStructNames; - - typedef std::list StructDeclarations; - StructDeclarations mStructDeclarations; - - typedef std::vector ScopeBracket; - ScopeBracket mScopeBracket; - unsigned int mScopeDepth; - int mUniqueIndex; // For creating unique names bool mContainsLoopDiscontinuity; bool mOutputLod0Function; bool mInsideDiscontinuousLoop; + int mNestedLoopDepth; TIntermSymbol *mExcessiveLoopIndex; - int mUniformRegister; - int mSamplerRegister; + void declareVaryingToList(const TType &type, TQualifier baseTypeQualifier, const TString &name, std::vector& fieldsOut); - TString registerString(TIntermSymbol *operand); - int samplerRegister(TIntermSymbol *sampler); - int uniformRegister(TIntermSymbol *uniform); - void declareUniform(const TType &type, const TString &name, int index); - static GLenum glVariableType(const TType &type); - static GLenum glVariablePrecision(const TType &type); + TString structInitializerString(int indent, const TStructure &structure, const TString &rhsStructName); - ActiveUniforms mActiveUniforms; + std::vector mActiveOutputVariables; + std::vector mActiveAttributes; + std::vector mActiveVaryings; + std::map mFlaggedStructMappedNames; + std::map mFlaggedStructOriginalNames; + + void makeFlaggedStructMaps(const std::vector &flaggedStructs); }; + } #endif // COMPILER_OUTPUTHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp index 1a1e0d140c..605612ac37 100644 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2013 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. // @@ -115,7 +115,7 @@ bool TParseContext::parseVectorFields(const TString& compString, int vecSize, TV // Look at a '.' field selector string and change it into offsets // for a matrix. // -bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TMatrixFields& fields, const TSourceLoc& line) +bool TParseContext::parseMatrixFields(const TString& compString, int matCols, int matRows, TMatrixFields& fields, const TSourceLoc& line) { fields.wholeRow = false; fields.wholeCol = false; @@ -151,7 +151,7 @@ bool TParseContext::parseMatrixFields(const TString& compString, int matSize, TM fields.col = compString[1] - '0'; } - if (fields.row >= matSize || fields.col >= matSize) { + if (fields.row >= matRows || fields.col >= matCols) { error(line, "matrix field selection out of range", compString.c_str()); return false; } @@ -277,6 +277,7 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIn case EOpIndexDirect: case EOpIndexIndirect: case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: return lValueErrorCheck(line, op, binaryNode->getLeft()); case EOpVectorSwizzle: errorReturn = lValueErrorCheck(line, op, binaryNode->getLeft()); @@ -285,21 +286,21 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIn TIntermTyped* rightNode = binaryNode->getRight(); TIntermAggregate *aggrNode = rightNode->getAsAggregate(); - - for (TIntermSequence::iterator p = aggrNode->getSequence().begin(); - p != aggrNode->getSequence().end(); p++) { + + for (TIntermSequence::iterator p = aggrNode->getSequence()->begin(); + p != aggrNode->getSequence()->end(); p++) { int value = (*p)->getAsTyped()->getAsConstantUnion()->getIConst(0); - offset[value]++; + offset[value]++; if (offset[value] > 1) { error(line, " l-value of swizzle cannot have duplicate components", op); return true; } } - } + } return errorReturn; - default: + default: break; } error(line, " l-value required", op); @@ -317,6 +318,8 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIn case EvqConst: message = "can't modify a const"; break; case EvqConstReadOnly: message = "can't modify a const"; break; case EvqAttribute: message = "can't modify an attribute"; break; + case EvqFragmentIn: message = "can't modify an input"; break; + case EvqVertexIn: message = "can't modify an input"; break; case EvqUniform: message = "can't modify a uniform"; break; case EvqVaryingIn: message = "can't modify a varying"; break; case EvqFragCoord: message = "can't modify gl_FragCoord"; break; @@ -327,16 +330,11 @@ bool TParseContext::lValueErrorCheck(const TSourceLoc& line, const char* op, TIn // // Type that can't be written to? // - switch (node->getBasicType()) { - case EbtSampler2D: - case EbtSamplerCube: - message = "can't modify a sampler"; - break; - case EbtVoid: + if (node->getBasicType() == EbtVoid) { message = "can't modify void"; - break; - default: - break; + } + if (IsSampler(node->getBasicType())) { + message = "can't modify a sampler"; } } @@ -396,7 +394,7 @@ bool TParseContext::constErrorCheck(TIntermTyped* node) // bool TParseContext::integerErrorCheck(TIntermTyped* node, const char* token) { - if (node->getBasicType() == EbtInt && node->getNominalSize() == 1) + if (node->isScalarInt()) return false; error(node->getLine(), "integer expression required", token); @@ -437,7 +435,7 @@ bool TParseContext::reservedErrorCheck(const TSourceLoc& line, const TString& id error(line, reservedErrMsg, "gl_"); return true; } - if (isWebGLBasedSpec(shaderSpec)) { + if (IsWebGLBasedSpec(shaderSpec)) { if (identifier.compare(0, 6, "webgl_") == 0) { error(line, reservedErrMsg, "webgl_"); return true; @@ -599,7 +597,7 @@ bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TIntermTyped* t // bool TParseContext::boolErrorCheck(const TSourceLoc& line, const TPublicType& pType) { - if (pType.type != EbtBool || pType.array || pType.matrix || (pType.size > 1)) { + if (pType.type != EbtBool || pType.isAggregate()) { error(line, "boolean expression expected", ""); return true; } @@ -628,11 +626,20 @@ bool TParseContext::samplerErrorCheck(const TSourceLoc& line, const TPublicType& bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType) { - if ((pType.qualifier == EvqVaryingIn || pType.qualifier == EvqVaryingOut || pType.qualifier == EvqAttribute) && - pType.type == EbtStruct) { - error(line, "cannot be used with a structure", getQualifierString(pType.qualifier)); - - return true; + switch (pType.qualifier) + { + case EvqVaryingIn: + case EvqVaryingOut: + case EvqAttribute: + case EvqVertexIn: + case EvqFragmentOut: + if (pType.type == EbtStruct) + { + error(line, "cannot be used with a structure", getQualifierString(pType.qualifier)); + return true; + } + + default: break; } if (pType.qualifier != EvqUniform && samplerErrorCheck(line, pType, "samplers must be uniform")) @@ -641,6 +648,17 @@ bool TParseContext::structQualifierErrorCheck(const TSourceLoc& line, const TPub return false; } +bool TParseContext::locationDeclaratorListCheck(const TSourceLoc& line, const TPublicType &pType) +{ + if (pType.layoutQualifier.location != -1) + { + error(line, "location must only be specified for a single input or output variable", "location"); + return true; + } + + return false; +} + bool TParseContext::parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type) { if ((qualifier == EvqOut || qualifier == EvqInOut) && @@ -657,7 +675,7 @@ bool TParseContext::containsSampler(TType& type) if (IsSampler(type.getBasicType())) return true; - if (type.getBasicType() == EbtStruct) { + if (type.getBasicType() == EbtStruct || type.isInterfaceBlock()) { const TFieldList& fields = type.getStruct()->fields(); for (unsigned int i = 0; i < fields.size(); ++i) { if (containsSampler(*fields[i]->type())) @@ -676,15 +694,49 @@ bool TParseContext::containsSampler(TType& type) bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size) { TIntermConstantUnion* constant = expr->getAsConstantUnion(); - if (constant == 0 || constant->getBasicType() != EbtInt) { + + if (constant == 0 || !constant->isScalarInt()) + { error(line, "array size must be a constant integer expression", ""); return true; } - size = constant->getIConst(0); + unsigned int unsignedSize = 0; + + if (constant->getBasicType() == EbtUInt) + { + unsignedSize = constant->getUConst(0); + size = static_cast(unsignedSize); + } + else + { + size = constant->getIConst(0); + + if (size < 0) + { + error(line, "array size must be non-negative", ""); + size = 1; + return true; + } + + unsignedSize = static_cast(size); + } + + if (size == 0) + { + error(line, "array size must be greater than zero", ""); + size = 1; + return true; + } + + // The size of arrays is restricted here to prevent issues further down the + // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to + // 4096 registers so this should be reasonable even for aggressively optimizable code. + const unsigned int sizeLimit = 65536; - if (size <= 0) { - error(line, "array size must be a positive integer", ""); + if (unsignedSize > sizeLimit) + { + error(line, "array size too large", ""); size = 1; return true; } @@ -699,7 +751,7 @@ bool TParseContext::arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* ex // bool TParseContext::arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type) { - if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqConst)) { + if ((type.qualifier == EvqAttribute) || (type.qualifier == EvqVertexIn) || (type.qualifier == EvqConst)) { error(line, "cannot declare arrays of this qualifier", TType(type).getCompleteString().c_str()); return true; } @@ -733,7 +785,7 @@ bool TParseContext::arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type // // Returns true if there was an error. // -bool TParseContext::arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable) +bool TParseContext::arrayErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType &type, TVariable*& variable) { // // Don't check for reserved word use until after we know it's not in the symbol table, @@ -742,7 +794,7 @@ bool TParseContext::arrayErrorCheck(const TSourceLoc& line, TString& identifier, bool builtIn = false; bool sameScope = false; - TSymbol* symbol = symbolTable.find(identifier, &builtIn, &sameScope); + TSymbol* symbol = symbolTable.find(identifier, 0, &builtIn, &sameScope); if (symbol == 0 || !sameScope) { if (reservedErrorCheck(line, identifier)) return true; @@ -752,7 +804,7 @@ bool TParseContext::arrayErrorCheck(const TSourceLoc& line, TString& identifier, if (type.arraySize) variable->getType().setArraySize(type.arraySize); - if (! symbolTable.insert(*variable)) { + if (! symbolTable.declare(variable)) { delete variable; error(line, "INTERNAL ERROR inserting new symbol", identifier.c_str()); return true; @@ -793,7 +845,7 @@ bool TParseContext::arrayErrorCheck(const TSourceLoc& line, TString& identifier, // // Returns true if there was an error. // -bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array) +bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, const TString& identifier, TPublicType& type, bool array) { if (type.qualifier == EvqConst) { @@ -825,14 +877,14 @@ bool TParseContext::nonInitConstErrorCheck(const TSourceLoc& line, TString& iden // // Returns true if there was an error. // -bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable) +bool TParseContext::nonInitErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& type, TVariable*& variable) { if (reservedErrorCheck(line, identifier)) recover(); variable = new TVariable(&identifier, TType(type)); - if (! symbolTable.insert(*variable)) { + if (! symbolTable.declare(variable)) { error(line, "redefinition", variable->getName().c_str()); delete variable; variable = 0; @@ -885,6 +937,45 @@ bool TParseContext::extensionErrorCheck(const TSourceLoc& line, const TString& e return false; } +bool TParseContext::singleDeclarationErrorCheck(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier) +{ + if (structQualifierErrorCheck(identifierLocation, publicType)) + return true; + + // check for layout qualifier issues + const TLayoutQualifier layoutQualifier = publicType.layoutQualifier; + + if (layoutQualifier.matrixPacking != EmpUnspecified) + { + error(identifierLocation, "layout qualifier", getMatrixPackingString(layoutQualifier.matrixPacking), "only valid for interface blocks"); + return true; + } + + if (layoutQualifier.blockStorage != EbsUnspecified) + { + error(identifierLocation, "layout qualifier", getBlockStorageString(layoutQualifier.blockStorage), "only valid for interface blocks"); + return true; + } + + if (publicType.qualifier != EvqVertexIn && publicType.qualifier != EvqFragmentOut && layoutLocationErrorCheck(identifierLocation, publicType.layoutQualifier)) + { + return true; + } + + return false; +} + +bool TParseContext::layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier) +{ + if (layoutQualifier.location != -1) + { + error(location, "invalid layout qualifier:", "location", "only valid on program inputs and outputs"); + return true; + } + + return false; +} + bool TParseContext::supportsExtension(const char* extension) { const TExtensionBehavior& extbehavior = extensionBehavior(); @@ -905,6 +996,22 @@ bool TParseContext::isExtensionEnabled(const char* extension) const return (iter->second == EBhEnable || iter->second == EBhRequire); } +void TParseContext::handleExtensionDirective(const TSourceLoc& loc, const char* extName, const char* behavior) +{ + pp::SourceLocation srcLoc; + srcLoc.file = loc.first_file; + srcLoc.line = loc.first_line; + directiveHandler.handleExtension(srcLoc, extName, behavior); +} + +void TParseContext::handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value) +{ + pp::SourceLocation srcLoc; + srcLoc.file = loc.first_file; + srcLoc.line = loc.first_line; + directiveHandler.handlePragma(srcLoc, name, value); +} + ///////////////////////////////////////////////////////////////////////////////// // // Non-Errors. @@ -916,14 +1023,14 @@ bool TParseContext::isExtensionEnabled(const char* extension) const // // Return the function symbol if found, otherwise 0. // -const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, bool *builtIn) +const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, int shaderVersion, bool *builtIn) { // First find by unmangled name to check whether the function name has been // hidden by a variable name or struct typename. // If a function is found, check for one with a matching argument list. - const TSymbol* symbol = symbolTable.find(call->getName(), builtIn); + const TSymbol* symbol = symbolTable.find(call->getName(), shaderVersion, builtIn); if (symbol == 0 || symbol->isFunction()) { - symbol = symbolTable.find(call->getMangledName(), builtIn); + symbol = symbolTable.find(call->getMangledName(), shaderVersion, builtIn); } if (symbol == 0) { @@ -943,7 +1050,7 @@ 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. // -bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType, +bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& identifier, TPublicType& pType, TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable) { TType type = TType(pType); @@ -959,7 +1066,7 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifi // add variable to symbol table // variable = new TVariable(&identifier, type); - if (! symbolTable.insert(*variable)) { + if (! symbolTable.declare(variable)) { error(line, "redefinition", variable->getName().c_str()); return true; // don't delete variable, it's used by error recovery, and the pool @@ -997,7 +1104,7 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, TString& identifi if (initializer->getAsConstantUnion()) { variable->shareConstPointer(initializer->getAsConstantUnion()->getUnionArrayPointer()); } else if (initializer->getAsSymbolNode()) { - const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol()); + const TSymbol* symbol = symbolTable.find(initializer->getAsSymbolNode()->getSymbol(), 0); const TVariable* tVar = static_cast(symbol); ConstantUnion* constArray = tVar->getConstPointer(); @@ -1035,8 +1142,8 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) // check if all the child nodes are constants so that they can be inserted into // the parent node - TIntermSequence &sequence = aggrNode->getSequence() ; - for (TIntermSequence::iterator p = sequence.begin(); p != sequence.end(); ++p) { + TIntermSequence *sequence = aggrNode->getSequence() ; + for (TIntermSequence::iterator p = sequence->begin(); p != sequence->end(); ++p) { if (!(*p)->getAsTyped()->getAsConstantUnion()) return false; } @@ -1044,269 +1151,514 @@ bool TParseContext::areAllChildConst(TIntermAggregate* aggrNode) return allConstant; } -// This function is used to test for the correctness of the parameters passed to various constructor functions -// and also convert them to the right datatype if it is allowed and required. -// -// Returns 0 for an error or the constructed node (aggregate or typed) for no error. -// -TIntermTyped* TParseContext::addConstructor(TIntermNode* node, const TType* type, TOperator op, TFunction* fnCall, const TSourceLoc& line) +TPublicType TParseContext::addFullySpecifiedType(TQualifier qualifier, TLayoutQualifier layoutQualifier, const TPublicType& typeSpecifier) { - if (node == 0) - return 0; + TPublicType returnType = typeSpecifier; + returnType.qualifier = qualifier; + returnType.layoutQualifier = layoutQualifier; - TIntermAggregate* aggrNode = node->getAsAggregate(); - - TFieldList::const_iterator memberFields; - if (op == EOpConstructStruct) - memberFields = type->getStruct()->fields().begin(); - - TType elementType = *type; - if (type->isArray()) - elementType.clearArrayness(); - - bool singleArg; - if (aggrNode) { - if (aggrNode->getOp() != EOpNull || aggrNode->getSequence().size() == 1) - singleArg = true; - else - singleArg = false; - } else - singleArg = true; - - TIntermTyped *newNode; - if (singleArg) { - // If structure constructor or array constructor is being called - // for only one parameter inside the structure, we need to call constructStruct function once. - if (type->isArray()) - newNode = constructStruct(node, &elementType, 1, node->getLine(), false); - else if (op == EOpConstructStruct) - newNode = constructStruct(node, (*memberFields)->type(), 1, node->getLine(), false); - else - newNode = constructBuiltIn(type, op, node, node->getLine(), false); + if (typeSpecifier.array) + { + error(typeSpecifier.line, "not supported", "first-class array"); + recover(); + returnType.setArray(false); + } - if (newNode && newNode->getAsAggregate()) { - TIntermTyped* constConstructor = foldConstConstructor(newNode->getAsAggregate(), *type); - if (constConstructor) - return constConstructor; + if (shaderVersion < 300) + { + if (qualifier == EvqAttribute && (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt)) + { + error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier)); + recover(); } - return newNode; - } - - // - // Handle list of arguments. - // - TIntermSequence &sequenceVector = aggrNode->getSequence() ; // Stores the information about the parameter to the constructor - // if the structure constructor contains more than one parameter, then construct - // each parameter - - int paramCount = 0; // keeps a track of the constructor parameter number being checked - - // for each parameter to the constructor call, check to see if the right type is passed or convert them - // to the right type if possible (and allowed). - // for structure constructors, just check if the right type is passed, no conversion is allowed. - - for (TIntermSequence::iterator p = sequenceVector.begin(); - p != sequenceVector.end(); p++, paramCount++) { - if (type->isArray()) - newNode = constructStruct(*p, &elementType, paramCount+1, node->getLine(), true); - else if (op == EOpConstructStruct) - newNode = constructStruct(*p, memberFields[paramCount]->type(), paramCount+1, node->getLine(), true); - else - newNode = constructBuiltIn(type, op, *p, node->getLine(), true); - - if (newNode) { - *p = newNode; + if ((qualifier == EvqVaryingIn || qualifier == EvqVaryingOut) && + (typeSpecifier.type == EbtBool || typeSpecifier.type == EbtInt)) + { + error(typeSpecifier.line, "cannot be bool or int", getQualifierString(qualifier)); + recover(); } } + else + { + switch (qualifier) + { + case EvqSmoothIn: + case EvqSmoothOut: + case EvqVertexOut: + case EvqFragmentIn: + case EvqCentroidOut: + case EvqCentroidIn: + if (typeSpecifier.type == EbtBool) + { + error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier)); + recover(); + } + if (typeSpecifier.type == EbtInt || typeSpecifier.type == EbtUInt) + { + error(typeSpecifier.line, "must use 'flat' interpolation here", getQualifierString(qualifier)); + recover(); + } + break; - TIntermTyped* constructor = intermediate.setAggregateOperator(aggrNode, op, line); - TIntermTyped* constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type); - if (constConstructor) - return constConstructor; + case EvqVertexIn: + case EvqFragmentOut: + case EvqFlatIn: + case EvqFlatOut: + if (typeSpecifier.type == EbtBool) + { + error(typeSpecifier.line, "cannot be bool", getQualifierString(qualifier)); + recover(); + } + break; - return constructor; + default: break; + } + } + + return returnType; } -TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type) +TIntermAggregate* TParseContext::parseSingleDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier) { - bool canBeFolded = areAllChildConst(aggrNode); - aggrNode->setType(type); - if (canBeFolded) { - bool returnVal = false; - ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()]; - if (aggrNode->getSequence().size() == 1) { - returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type, true); - } - else { - returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), symbolTable, type); - } - if (returnVal) - return 0; + TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation); + TIntermAggregate* aggregate = intermediate.makeAggregate(symbol, identifierLocation); - return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine()); + if (identifier != "") + { + if (singleDeclarationErrorCheck(publicType, identifierLocation, identifier)) + recover(); + + // this error check can mutate the type + if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, false)) + recover(); + + TVariable* variable = 0; + + if (nonInitErrorCheck(identifierLocation, identifier, publicType, variable)) + recover(); + + if (variable && symbol) + { + symbol->setId(variable->getUniqueId()); + } } - return 0; + return aggregate; } -// Function for constructor implementation. Calls addUnaryMath with appropriate EOp value -// for the parameter to the constructor (passed to this function). Essentially, it converts -// the parameter types correctly. If a constructor expects an int (like ivec2) and is passed a -// float, then float is converted to int. -// -// Returns 0 for an error or the constructed node. -// -TIntermTyped* TParseContext::constructBuiltIn(const TType* type, TOperator op, TIntermNode* node, const TSourceLoc& line, bool subset) +TIntermAggregate* TParseContext::parseSingleArrayDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& indexLocation, TIntermTyped *indexExpression) { - TIntermTyped* newNode; - TOperator basicOp; + if (singleDeclarationErrorCheck(publicType, identifierLocation, identifier)) + recover(); - // - // First, convert types as needed. - // - switch (op) { - case EOpConstructVec2: - case EOpConstructVec3: - case EOpConstructVec4: - case EOpConstructMat2: - case EOpConstructMat3: - case EOpConstructMat4: - case EOpConstructFloat: - basicOp = EOpConstructFloat; - break; + // this error check can mutate the type + if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, true)) + recover(); - case EOpConstructIVec2: - case EOpConstructIVec3: - case EOpConstructIVec4: - case EOpConstructInt: - basicOp = EOpConstructInt; - break; + if (arrayTypeErrorCheck(indexLocation, publicType) || arrayQualifierErrorCheck(indexLocation, publicType)) + { + recover(); + } - case EOpConstructBVec2: - case EOpConstructBVec3: - case EOpConstructBVec4: - case EOpConstructBool: - basicOp = EOpConstructBool; - break; + TPublicType arrayType = publicType; - default: - error(line, "unsupported construction", ""); + int size; + if (arraySizeErrorCheck(identifierLocation, indexExpression, size)) + { recover(); - - return 0; } - newNode = intermediate.addUnaryMath(basicOp, node, node->getLine(), symbolTable); - if (newNode == 0) { - error(line, "can't convert", "constructor"); - return 0; + else + { + arrayType.setArray(true, size); } - // - // Now, if there still isn't an operation to do the construction, and we need one, add one. - // - - // Otherwise, skip out early. - if (subset || (newNode != node && newNode->getType() == *type)) - return newNode; + TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(arrayType), identifierLocation); + TIntermAggregate* aggregate = intermediate.makeAggregate(symbol, identifierLocation); + TVariable* variable = 0; + + if (arrayErrorCheck(identifierLocation, identifier, arrayType, variable)) + recover(); + + if (variable && symbol) + { + symbol->setId(variable->getUniqueId()); + } - // setAggregateOperator will insert a new node for the constructor, as needed. - return intermediate.setAggregateOperator(newNode, op, line); + return aggregate; } -// This function tests for the type of the parameters to the structures constructors. Raises -// an error message if the expected type does not match the parameter passed to the constructor. -// -// Returns 0 for an error or the input node itself if the expected and the given parameter types match. -// -TIntermTyped* TParseContext::constructStruct(TIntermNode* node, TType* type, int paramCount, const TSourceLoc& line, bool subset) +TIntermAggregate* TParseContext::parseSingleInitDeclaration(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer) { - if (*type == node->getAsTyped()->getType()) { - if (subset) - return node->getAsTyped(); - else - return intermediate.setAggregateOperator(node->getAsTyped(), EOpConstructStruct, line); - } else { - std::stringstream extraInfoStream; - extraInfoStream << "cannot convert parameter " << paramCount - << " from '" << node->getAsTyped()->getType().getBasicString() - << "' to '" << type->getBasicString() << "'"; - std::string extraInfo = extraInfoStream.str(); - error(line, "", "constructor", extraInfo.c_str()); + if (singleDeclarationErrorCheck(publicType, identifierLocation, identifier)) recover(); - } - return 0; + TIntermNode* intermNode; + if (!executeInitializer(identifierLocation, identifier, publicType, initializer, intermNode)) + { + // + // Build intermediate representation + // + return intermNode ? intermediate.makeAggregate(intermNode, initLocation) : NULL; + } + else + { + recover(); + return NULL; + } } -// -// This function returns the tree representation for the vector field(s) being accessed from contant vector. -// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is -// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol -// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of -// a constant matrix. -// -TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line) +TIntermAggregate* TParseContext::parseDeclarator(TPublicType &publicType, TIntermAggregate *aggregateDeclaration, TSymbol *identifierSymbol, const TSourceLoc& identifierLocation, const TString &identifier) { - TIntermTyped* typedNode; - TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); + if (publicType.type == EbtInvariant && !identifierSymbol) + { + error(identifierLocation, "undeclared identifier declared as invariant", identifier.c_str()); + recover(); + } - ConstantUnion *unionArray; - if (tempConstantNode) { - unionArray = tempConstantNode->getUnionArrayPointer(); + TIntermSymbol* symbol = intermediate.addSymbol(0, identifier, TType(publicType), identifierLocation); + TIntermAggregate* intermAggregate = intermediate.growAggregate(aggregateDeclaration, symbol, identifierLocation); - if (!unionArray) { - return node; - } - } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error - error(line, "Cannot offset into the vector", "Error"); + if (structQualifierErrorCheck(identifierLocation, publicType)) recover(); - return 0; - } + if (locationDeclaratorListCheck(identifierLocation, publicType)) + recover(); - ConstantUnion* constArray = new ConstantUnion[fields.num]; + if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, false)) + recover(); - for (int i = 0; i < fields.num; i++) { - if (fields.offsets[i] >= node->getType().getNominalSize()) { - std::stringstream extraInfoStream; - extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'"; - std::string extraInfo = extraInfoStream.str(); - error(line, "", "[", extraInfo.c_str()); - recover(); - fields.offsets[i] = 0; - } - - constArray[i] = unionArray[fields.offsets[i]]; + TVariable* variable = 0; + if (nonInitErrorCheck(identifierLocation, identifier, publicType, variable)) + recover(); + if (symbol && variable) + symbol->setId(variable->getUniqueId()); - } - typedNode = intermediate.addConstantUnion(constArray, node->getType(), line); - return typedNode; + return intermAggregate; } -// -// This function returns the column being accessed from a constant matrix. The values are retrieved from -// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input -// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a -// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure) -// -TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line) +TIntermAggregate* TParseContext::parseArrayDeclarator(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& arrayLocation, TIntermNode *declaratorList, TIntermTyped *indexExpression) { - TIntermTyped* typedNode; - TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); + if (structQualifierErrorCheck(identifierLocation, publicType)) + recover(); - if (index >= node->getType().getNominalSize()) { - std::stringstream extraInfoStream; - extraInfoStream << "matrix field selection out of range '" << index << "'"; - std::string extraInfo = extraInfoStream.str(); - error(line, "", "[", extraInfo.c_str()); + if (locationDeclaratorListCheck(identifierLocation, publicType)) recover(); - index = 0; + + if (nonInitConstErrorCheck(identifierLocation, identifier, publicType, true)) + recover(); + + if (arrayTypeErrorCheck(arrayLocation, publicType) || arrayQualifierErrorCheck(arrayLocation, publicType)) + { + recover(); + } + else if (indexExpression) + { + int size; + if (arraySizeErrorCheck(arrayLocation, indexExpression, size)) + recover(); + TPublicType arrayType(publicType); + arrayType.setArray(true, size); + TVariable* variable = NULL; + if (arrayErrorCheck(arrayLocation, identifier, arrayType, variable)) + recover(); + TType type = TType(arrayType); + type.setArraySize(size); + + return intermediate.growAggregate(declaratorList, intermediate.addSymbol(variable ? variable->getUniqueId() : 0, identifier, type, identifierLocation), identifierLocation); + } + else + { + TPublicType arrayType(publicType); + arrayType.setArray(true); + TVariable* variable = NULL; + if (arrayErrorCheck(arrayLocation, identifier, arrayType, variable)) + recover(); + } + + return NULL; +} + +TIntermAggregate* TParseContext::parseInitDeclarator(TPublicType &publicType, TIntermAggregate *declaratorList, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer) +{ + if (structQualifierErrorCheck(identifierLocation, publicType)) + recover(); + + if (locationDeclaratorListCheck(identifierLocation, publicType)) + recover(); + + TIntermNode* intermNode; + if (!executeInitializer(identifierLocation, identifier, publicType, initializer, intermNode)) + { + // + // build the intermediate representation + // + if (intermNode) + { + return intermediate.growAggregate(declaratorList, intermNode, initLocation); + } + else + { + return declaratorList; + } + } + else + { + recover(); + return NULL; + } +} + +void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier) +{ + if (typeQualifier.qualifier != EvqUniform) + { + error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "global layout must be uniform"); + recover(); + return; + } + + const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier; + ASSERT(!layoutQualifier.isEmpty()); + + if (shaderVersion < 300) + { + error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 only", "layout"); + recover(); + return; + } + + if (layoutLocationErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier)) + { + recover(); + return; + } + + if (layoutQualifier.matrixPacking != EmpUnspecified) + { + defaultMatrixPacking = layoutQualifier.matrixPacking; + } + + if (layoutQualifier.blockStorage != EbsUnspecified) + { + defaultBlockStorage = layoutQualifier.blockStorage; + } +} + +TFunction *TParseContext::addConstructorFunc(TPublicType publicType) +{ + TOperator op = EOpNull; + if (publicType.userDef) + { + op = EOpConstructStruct; + } + else + { + switch (publicType.type) + { + case EbtFloat: + if (publicType.isMatrix()) + { + // TODO: non-square matrices + switch(publicType.getCols()) + { + case 2: op = EOpConstructMat2; break; + case 3: op = EOpConstructMat3; break; + case 4: op = EOpConstructMat4; break; + } + } + else + { + switch(publicType.getNominalSize()) + { + case 1: op = EOpConstructFloat; break; + case 2: op = EOpConstructVec2; break; + case 3: op = EOpConstructVec3; break; + case 4: op = EOpConstructVec4; break; + } + } + break; + + case EbtInt: + switch(publicType.getNominalSize()) + { + case 1: op = EOpConstructInt; break; + case 2: op = EOpConstructIVec2; break; + case 3: op = EOpConstructIVec3; break; + case 4: op = EOpConstructIVec4; break; + } + break; + + case EbtUInt: + switch(publicType.getNominalSize()) + { + case 1: op = EOpConstructUInt; break; + case 2: op = EOpConstructUVec2; break; + case 3: op = EOpConstructUVec3; break; + case 4: op = EOpConstructUVec4; break; + } + break; + + case EbtBool: + switch(publicType.getNominalSize()) + { + case 1: op = EOpConstructBool; break; + case 2: op = EOpConstructBVec2; break; + case 3: op = EOpConstructBVec3; break; + case 4: op = EOpConstructBVec4; break; + } + break; + + default: break; + } + + if (op == EOpNull) + { + error(publicType.line, "cannot construct this type", getBasicString(publicType.type)); + recover(); + publicType.type = EbtFloat; + op = EOpConstructFloat; + } + } + + TString tempString; + TType type(publicType); + return new TFunction(&tempString, type, op); +} + +// This function is used to test for the correctness of the parameters passed to various constructor functions +// and also convert them to the right datatype if it is allowed and required. +// +// Returns 0 for an error or the constructed node (aggregate or typed) for no error. +// +TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, const TType *type, TOperator op, TFunction *fnCall, const TSourceLoc &line) +{ + TIntermAggregate *aggregateArguments = arguments->getAsAggregate(); + + if (!aggregateArguments) + { + aggregateArguments = new TIntermAggregate; + aggregateArguments->getSequence()->push_back(arguments); + } + + if (op == EOpConstructStruct) + { + const TFieldList &fields = type->getStruct()->fields(); + TIntermSequence *args = aggregateArguments->getSequence(); + + for (size_t i = 0; i < fields.size(); i++) + { + if ((*args)[i]->getAsTyped()->getType() != *fields[i]->type()) + { + error(line, "Structure constructor arguments do not match structure fields", "Error"); + recover(); + + return 0; + } + } + } + + // Turn the argument list itself into a constructor + TIntermTyped *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line); + TIntermTyped *constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type); + if (constConstructor) + { + return constConstructor; + } + + return constructor; +} + +TIntermTyped* TParseContext::foldConstConstructor(TIntermAggregate* aggrNode, const TType& type) +{ + bool canBeFolded = areAllChildConst(aggrNode); + aggrNode->setType(type); + if (canBeFolded) { + bool returnVal = false; + ConstantUnion* unionArray = new ConstantUnion[type.getObjectSize()]; + if (aggrNode->getSequence()->size() == 1) { + returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type, true); + } + else { + returnVal = intermediate.parseConstTree(aggrNode->getLine(), aggrNode, unionArray, aggrNode->getOp(), type); + } + if (returnVal) + return 0; + + return intermediate.addConstantUnion(unionArray, type, aggrNode->getLine()); + } + + return 0; +} + +// +// This function returns the tree representation for the vector field(s) being accessed from contant vector. +// If only one component of vector is accessed (v.x or v[0] where v is a contant vector), then a contant node is +// returned, else an aggregate node is returned (for v.xy). The input to this function could either be the symbol +// node or it could be the intermediate tree representation of accessing fields in a constant structure or column of +// a constant matrix. +// +TIntermTyped* TParseContext::addConstVectorNode(TVectorFields& fields, TIntermTyped* node, const TSourceLoc& line) +{ + TIntermTyped* typedNode; + TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); + + ConstantUnion *unionArray; + if (tempConstantNode) { + unionArray = tempConstantNode->getUnionArrayPointer(); + + if (!unionArray) { + return node; + } + } else { // The node has to be either a symbol node or an aggregate node or a tempConstant node, else, its an error + error(line, "Cannot offset into the vector", "Error"); + recover(); + + return 0; + } + + ConstantUnion* constArray = new ConstantUnion[fields.num]; + + for (int i = 0; i < fields.num; i++) { + if (fields.offsets[i] >= node->getType().getNominalSize()) { + std::stringstream extraInfoStream; + extraInfoStream << "vector field selection out of range '" << fields.offsets[i] << "'"; + std::string extraInfo = extraInfoStream.str(); + error(line, "", "[", extraInfo.c_str()); + recover(); + fields.offsets[i] = 0; + } + + constArray[i] = unionArray[fields.offsets[i]]; + + } + typedNode = intermediate.addConstantUnion(constArray, node->getType(), line); + return typedNode; +} + +// +// This function returns the column being accessed from a constant matrix. The values are retrieved from +// the symbol table and parse-tree is built for a vector (each column of a matrix is a vector). The input +// to the function could either be a symbol node (m[0] where m is a constant matrix)that represents a +// constant matrix or it could be the tree representation of the constant matrix (s.m1[0] where s is a constant structure) +// +TIntermTyped* TParseContext::addConstMatrixNode(int index, TIntermTyped* node, const TSourceLoc& line) +{ + TIntermTyped* typedNode; + TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); + + if (index >= node->getType().getCols()) { + std::stringstream extraInfoStream; + extraInfoStream << "matrix field selection out of range '" << index << "'"; + std::string extraInfo = extraInfoStream.str(); + error(line, "", "[", extraInfo.c_str()); + recover(); + index = 0; } if (tempConstantNode) { ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); - int size = tempConstantNode->getType().getNominalSize(); + int size = tempConstantNode->getType().getCols(); typedNode = intermediate.addConstantUnion(&unionArray[size*index], tempConstantNode->getType(), line); } else { error(line, "Cannot offset into the matrix", "Error"); @@ -1342,9 +1694,9 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, co } if (tempConstantNode) { - size_t arrayElementSize = arrayElementType.getObjectSize(); - ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); - typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line); + size_t arrayElementSize = arrayElementType.getObjectSize(); + ConstantUnion* unionArray = tempConstantNode->getUnionArrayPointer(); + typedNode = intermediate.addConstantUnion(&unionArray[arrayElementSize * index], tempConstantNode->getType(), line); } else { error(line, "Cannot offset into the array", "Error"); recover(); @@ -1361,11 +1713,11 @@ TIntermTyped* TParseContext::addConstArrayNode(int index, TIntermTyped* node, co // If there is an embedded/nested struct, it appropriately calls addConstStructNested or addConstStructFromAggr // function and returns the parse-tree with the values of the embedded/nested struct. // -TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* node, const TSourceLoc& line) +TIntermTyped* TParseContext::addConstStruct(const TString &identifier, TIntermTyped *node, const TSourceLoc& line) { const TFieldList& fields = node->getType().getStruct()->fields(); - size_t instanceSize = 0; + for (size_t index = 0; index < fields.size(); ++index) { if (fields[index]->name() == identifier) { break; @@ -1374,8 +1726,8 @@ TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* n } } - TIntermTyped* typedNode = 0; - TIntermConstantUnion* tempConstantNode = node->getAsConstantUnion(); + TIntermTyped *typedNode; + TIntermConstantUnion *tempConstantNode = node->getAsConstantUnion(); if (tempConstantNode) { ConstantUnion* constArray = tempConstantNode->getUnionArrayPointer(); @@ -1390,6 +1742,146 @@ TIntermTyped* TParseContext::addConstStruct(TString& identifier, TIntermTyped* n return typedNode; } +// +// Interface/uniform blocks +// +TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList, + const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine) +{ + if (reservedErrorCheck(nameLine, blockName)) + recover(); + + if (typeQualifier.qualifier != EvqUniform) + { + error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "interface blocks must be uniform"); + recover(); + } + + TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier; + if (layoutLocationErrorCheck(typeQualifier.line, blockLayoutQualifier)) + { + recover(); + } + + if (blockLayoutQualifier.matrixPacking == EmpUnspecified) + { + blockLayoutQualifier.matrixPacking = defaultMatrixPacking; + } + + if (blockLayoutQualifier.blockStorage == EbsUnspecified) + { + blockLayoutQualifier.blockStorage = defaultBlockStorage; + } + + TSymbol* blockNameSymbol = new TInterfaceBlockName(&blockName); + if (!symbolTable.declare(blockNameSymbol)) { + error(nameLine, "redefinition", blockName.c_str(), "interface block name"); + recover(); + } + + // check for sampler types and apply layout qualifiers + for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) { + TField* field = (*fieldList)[memberIndex]; + TType* fieldType = field->type(); + if (IsSampler(fieldType->getBasicType())) { + error(field->line(), "unsupported type", fieldType->getBasicString(), "sampler types are not allowed in interface blocks"); + recover(); + } + + const TQualifier qualifier = fieldType->getQualifier(); + switch (qualifier) + { + case EvqGlobal: + case EvqUniform: + break; + default: + error(field->line(), "invalid qualifier on interface block member", getQualifierString(qualifier)); + recover(); + break; + } + + // check layout qualifiers + TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier(); + if (layoutLocationErrorCheck(field->line(), fieldLayoutQualifier)) + { + recover(); + } + + if (fieldLayoutQualifier.blockStorage != EbsUnspecified) + { + error(field->line(), "invalid layout qualifier:", getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here"); + recover(); + } + + if (fieldLayoutQualifier.matrixPacking == EmpUnspecified) + { + fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking; + } + else if (!fieldType->isMatrix()) + { + error(field->line(), "invalid layout qualifier:", getMatrixPackingString(fieldLayoutQualifier.matrixPacking), "can only be used on matrix types"); + recover(); + } + + fieldType->setLayoutQualifier(fieldLayoutQualifier); + } + + // add array index + int arraySize = 0; + if (arrayIndex != NULL) + { + if (arraySizeErrorCheck(arrayIndexLine, arrayIndex, arraySize)) + recover(); + } + + TInterfaceBlock* interfaceBlock = new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier); + TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier, arraySize); + + TString symbolName = ""; + int symbolId = 0; + + if (!instanceName) + { + // define symbols for the members of the interface block + for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) + { + TField* field = (*fieldList)[memberIndex]; + TType* fieldType = field->type(); + + // set parent pointer of the field variable + fieldType->setInterfaceBlock(interfaceBlock); + + TVariable* fieldVariable = new TVariable(&field->name(), *fieldType); + fieldVariable->setQualifier(typeQualifier.qualifier); + + if (!symbolTable.declare(fieldVariable)) { + error(field->line(), "redefinition", field->name().c_str(), "interface block member name"); + recover(); + } + } + } + else + { + // add a symbol for this interface block + TVariable* instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false); + instanceTypeDef->setQualifier(typeQualifier.qualifier); + + if (!symbolTable.declare(instanceTypeDef)) { + error(instanceLine, "redefinition", instanceName->c_str(), "interface block instance name"); + recover(); + } + + symbolId = instanceTypeDef->getUniqueId(); + symbolName = instanceTypeDef->getName(); + } + + TIntermAggregate *aggregate = intermediate.makeAggregate(intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line), nameLine); + aggregate->setOp(EOpDeclaration); + + exitStructDeclaration(); + return aggregate; +} + bool TParseContext::enterStructDeclaration(const TSourceLoc& line, const TString& identifier) { ++structNestingLevel; @@ -1418,7 +1910,7 @@ const int kWebGLMaxStructNesting = 4; bool TParseContext::structNestingErrorCheck(const TSourceLoc& line, const TField& field) { - if (!isWebGLBasedSpec(shaderSpec)) { + if (!IsWebGLBasedSpec(shaderSpec)) { return false; } @@ -1531,6 +2023,17 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, co } else { + if (baseExpression->isInterfaceBlock()) + { + error(location, "", "[", "array indexes for interface blocks arrays must be constant integral expressions"); + recover(); + } + else if (baseExpression->getQualifier() == EvqFragmentOut) + { + error(location, "", "[", "array indexes for fragment outputs must be constant integral expressions"); + recover(); + } + indexedExpression = intermediate.addIndex(EOpIndexIndirect, baseExpression, indexExpression, location); } @@ -1548,9 +2051,14 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, co TType copyOfType(baseType.getStruct()); indexedExpression->setType(copyOfType); } + else if (baseType.isInterfaceBlock()) + { + TType copyOfType(baseType.getInterfaceBlock(), baseType.getQualifier(), baseType.getLayoutQualifier(), 0); + indexedExpression->setType(copyOfType); + } else { - indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->isMatrix())); + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, baseExpression->getNominalSize(), baseExpression->getSecondarySize())); } if (baseExpression->getType().getQualifier() == EvqConst) @@ -1561,7 +2069,7 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, co else if (baseExpression->isMatrix()) { TQualifier qualifier = baseExpression->getType().getQualifier() == EvqConst ? EvqConst : EvqTemporary; - indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getNominalSize())); + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), qualifier, baseExpression->getRows())); } else if (baseExpression->isVector()) { @@ -1576,6 +2084,408 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, co return indexedExpression; } +TIntermTyped* TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc& dotLocation, const TString &fieldString, const TSourceLoc& fieldLocation) +{ + TIntermTyped *indexedExpression = NULL; + + if (baseExpression->isArray()) + { + error(fieldLocation, "cannot apply dot operator to an array", "."); + recover(); + } + + if (baseExpression->isVector()) + { + TVectorFields fields; + if (!parseVectorFields(fieldString, baseExpression->getNominalSize(), fields, fieldLocation)) + { + fields.num = 1; + fields.offsets[0] = 0; + recover(); + } + + if (baseExpression->getType().getQualifier() == EvqConst) + { + // constant folding for vector fields + indexedExpression = addConstVectorNode(fields, baseExpression, fieldLocation); + if (indexedExpression == 0) + { + recover(); + indexedExpression = baseExpression; + } + else + { + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqConst, (int) (fieldString).size())); + } + } + else + { + TString vectorString = fieldString; + TIntermTyped* index = intermediate.addSwizzle(fields, fieldLocation); + indexedExpression = intermediate.addIndex(EOpVectorSwizzle, baseExpression, index, dotLocation); + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(), EvqTemporary, (int) vectorString.size())); + } + } + else if (baseExpression->isMatrix()) + { + TMatrixFields fields; + if (!parseMatrixFields(fieldString, baseExpression->getCols(), baseExpression->getRows(), fields, fieldLocation)) + { + fields.wholeRow = false; + fields.wholeCol = false; + fields.row = 0; + fields.col = 0; + recover(); + } + + if (fields.wholeRow || fields.wholeCol) + { + error(dotLocation, " non-scalar fields not implemented yet", "."); + recover(); + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(0); + TIntermTyped* index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), fieldLocation); + indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation); + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision(),EvqTemporary, baseExpression->getCols(), baseExpression->getRows())); + } + else + { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(fields.col * baseExpression->getRows() + fields.row); + TIntermTyped* index = intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), fieldLocation); + indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, index, dotLocation); + indexedExpression->setType(TType(baseExpression->getBasicType(), baseExpression->getPrecision())); + } + } + else if (baseExpression->getBasicType() == EbtStruct) + { + bool fieldFound = false; + const TFieldList& fields = baseExpression->getType().getStruct()->fields(); + if (fields.empty()) + { + error(dotLocation, "structure has no fields", "Internal Error"); + recover(); + indexedExpression = baseExpression; + } + else + { + unsigned int i; + for (i = 0; i < fields.size(); ++i) + { + if (fields[i]->name() == fieldString) + { + fieldFound = true; + break; + } + } + if (fieldFound) + { + if (baseExpression->getType().getQualifier() == EvqConst) + { + indexedExpression = addConstStruct(fieldString, baseExpression, dotLocation); + if (indexedExpression == 0) + { + recover(); + indexedExpression = baseExpression; + } + else + { + indexedExpression->setType(*fields[i]->type()); + // change the qualifier of the return type, not of the structure field + // as the structure definition is shared between various structures. + indexedExpression->getTypePointer()->setQualifier(EvqConst); + } + } + else + { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(i); + TIntermTyped* index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation); + indexedExpression = intermediate.addIndex(EOpIndexDirectStruct, baseExpression, index, dotLocation); + indexedExpression->setType(*fields[i]->type()); + } + } + else + { + error(dotLocation, " no such field in structure", fieldString.c_str()); + recover(); + indexedExpression = baseExpression; + } + } + } + else if (baseExpression->isInterfaceBlock()) + { + bool fieldFound = false; + const TFieldList& fields = baseExpression->getType().getInterfaceBlock()->fields(); + if (fields.empty()) + { + error(dotLocation, "interface block has no fields", "Internal Error"); + recover(); + indexedExpression = baseExpression; + } + else + { + unsigned int i; + for (i = 0; i < fields.size(); ++i) + { + if (fields[i]->name() == fieldString) + { + fieldFound = true; + break; + } + } + if (fieldFound) + { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setIConst(i); + TIntermTyped* index = intermediate.addConstantUnion(unionArray, *fields[i]->type(), fieldLocation); + indexedExpression = intermediate.addIndex(EOpIndexDirectInterfaceBlock, baseExpression, index, dotLocation); + indexedExpression->setType(*fields[i]->type()); + } + else + { + error(dotLocation, " no such field in interface block", fieldString.c_str()); + recover(); + indexedExpression = baseExpression; + } + } + } + else + { + if (shaderVersion < 300) + { + error(dotLocation, " field selection requires structure, vector, or matrix on left hand side", fieldString.c_str()); + } + else + { + error(dotLocation, " field selection requires structure, vector, matrix, or interface block on left hand side", fieldString.c_str()); + } + recover(); + indexedExpression = baseExpression; + } + + return indexedExpression; +} + +TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine) +{ + TLayoutQualifier qualifier; + + qualifier.location = -1; + qualifier.matrixPacking = EmpUnspecified; + qualifier.blockStorage = EbsUnspecified; + + if (qualifierType == "shared") + { + qualifier.blockStorage = EbsShared; + } + else if (qualifierType == "packed") + { + qualifier.blockStorage = EbsPacked; + } + else if (qualifierType == "std140") + { + qualifier.blockStorage = EbsStd140; + } + else if (qualifierType == "row_major") + { + qualifier.matrixPacking = EmpRowMajor; + } + else if (qualifierType == "column_major") + { + qualifier.matrixPacking = EmpColumnMajor; + } + else if (qualifierType == "location") + { + error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "location requires an argument"); + recover(); + } + else + { + error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str()); + recover(); + } + + return qualifier; +} + +TLayoutQualifier TParseContext::parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine) +{ + TLayoutQualifier qualifier; + + qualifier.location = -1; + qualifier.matrixPacking = EmpUnspecified; + qualifier.blockStorage = EbsUnspecified; + + if (qualifierType != "location") + { + error(qualifierTypeLine, "invalid layout qualifier", qualifierType.c_str(), "only location may have arguments"); + recover(); + } + else + { + // must check that location is non-negative + if (intValue < 0) + { + error(intValueLine, "out of range:", intValueString.c_str(), "location must be non-negative"); + recover(); + } + else + { + qualifier.location = intValue; + } + } + + return qualifier; +} + +TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier) +{ + TLayoutQualifier joinedQualifier = leftQualifier; + + if (rightQualifier.location != -1) + { + joinedQualifier.location = rightQualifier.location; + } + if (rightQualifier.matrixPacking != EmpUnspecified) + { + joinedQualifier.matrixPacking = rightQualifier.matrixPacking; + } + if (rightQualifier.blockStorage != EbsUnspecified) + { + joinedQualifier.blockStorage = rightQualifier.blockStorage; + } + + return joinedQualifier; +} + +TPublicType TParseContext::joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier, + const TSourceLoc &storageLoc, TQualifier storageQualifier) +{ + TQualifier mergedQualifier = EvqSmoothIn; + + if (storageQualifier == EvqFragmentIn) { + if (interpolationQualifier == EvqSmooth) + mergedQualifier = EvqSmoothIn; + else if (interpolationQualifier == EvqFlat) + mergedQualifier = EvqFlatIn; + else UNREACHABLE(); + } + else if (storageQualifier == EvqCentroidIn) { + if (interpolationQualifier == EvqSmooth) + mergedQualifier = EvqCentroidIn; + else if (interpolationQualifier == EvqFlat) + mergedQualifier = EvqFlatIn; + else UNREACHABLE(); + } + else if (storageQualifier == EvqVertexOut) { + if (interpolationQualifier == EvqSmooth) + mergedQualifier = EvqSmoothOut; + else if (interpolationQualifier == EvqFlat) + mergedQualifier = EvqFlatOut; + else UNREACHABLE(); + } + else if (storageQualifier == EvqCentroidOut) { + if (interpolationQualifier == EvqSmooth) + mergedQualifier = EvqCentroidOut; + else if (interpolationQualifier == EvqFlat) + mergedQualifier = EvqFlatOut; + else UNREACHABLE(); + } + else { + error(interpolationLoc, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getInterpolationString(interpolationQualifier)); + recover(); + + mergedQualifier = storageQualifier; + } + + TPublicType type; + type.setBasic(EbtVoid, mergedQualifier, storageLoc); + return type; +} + +TFieldList *TParseContext::addStructDeclaratorList(const TPublicType& typeSpecifier, TFieldList *fieldList) +{ + if (voidErrorCheck(typeSpecifier.line, (*fieldList)[0]->name(), typeSpecifier)) { + recover(); + } + + for (unsigned int i = 0; i < fieldList->size(); ++i) { + // + // Careful not to replace already known aspects of type, like array-ness + // + TType* type = (*fieldList)[i]->type(); + type->setBasicType(typeSpecifier.type); + type->setPrimarySize(typeSpecifier.primarySize); + type->setSecondarySize(typeSpecifier.secondarySize); + type->setPrecision(typeSpecifier.precision); + type->setQualifier(typeSpecifier.qualifier); + type->setLayoutQualifier(typeSpecifier.layoutQualifier); + + // don't allow arrays of arrays + if (type->isArray()) { + if (arrayTypeErrorCheck(typeSpecifier.line, typeSpecifier)) + recover(); + } + if (typeSpecifier.array) + type->setArraySize(typeSpecifier.arraySize); + if (typeSpecifier.userDef) { + type->setStruct(typeSpecifier.userDef->getStruct()); + } + + if (structNestingErrorCheck(typeSpecifier.line, *(*fieldList)[i])) { + recover(); + } + } + + return fieldList; +} + +TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSourceLoc& nameLine, const TString *structName, TFieldList* fieldList) +{ + TStructure* structure = new TStructure(structName, fieldList); + TType* structureType = new TType(structure); + + structure->setUniqueId(TSymbolTable::nextUniqueId()); + + if (!structName->empty()) + { + if (reservedErrorCheck(nameLine, *structName)) + { + recover(); + } + TVariable* userTypeDef = new TVariable(structName, *structureType, true); + if (!symbolTable.declare(userTypeDef)) { + error(nameLine, "redefinition", structName->c_str(), "struct"); + recover(); + } + } + + // ensure we do not specify any storage qualifiers on the struct members + for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++) + { + const TField &field = *(*fieldList)[typeListIndex]; + const TQualifier qualifier = field.type()->getQualifier(); + switch (qualifier) + { + case EvqGlobal: + case EvqTemporary: + break; + default: + error(field.line(), "invalid qualifier on struct member", getQualifierString(qualifier)); + recover(); + break; + } + } + + TPublicType publicType; + publicType.setBasic(EbtStruct, EvqTemporary, structLine); + publicType.userDef = structureType; + exitStructDeclaration(); + + return publicType; +} + // // Parse an array of strings using yyparse. // diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.h b/src/3rdparty/angle/src/compiler/translator/ParseContext.h index b324e575d3..a402eec78e 100644 --- a/src/3rdparty/angle/src/compiler/translator/ParseContext.h +++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.h @@ -1,17 +1,17 @@ // -// Copyright (c) 2002-2013 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. // #ifndef _PARSER_HELPER_INCLUDED_ #define _PARSER_HELPER_INCLUDED_ +#include "compiler/translator/Compiler.h" #include "compiler/translator/Diagnostics.h" #include "compiler/translator/DirectiveHandler.h" #include "compiler/translator/localintermediate.h" -#include "compiler/preprocessor/Preprocessor.h" -#include "compiler/translator/ShHandle.h" #include "compiler/translator/SymbolTable.h" +#include "compiler/preprocessor/Preprocessor.h" struct TMatrixFields { bool wholeRow; @@ -25,7 +25,7 @@ struct TMatrixFields { // they can be passed to the parser without needing a global. // struct TParseContext { - TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, ShShaderType type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) : + TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, sh::GLenum type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) : intermediate(interm), symbolTable(symt), shaderType(type), @@ -38,14 +38,18 @@ struct TParseContext { currentFunctionType(NULL), functionReturnsValue(false), checksPrecisionErrors(checksPrecErrors), + defaultMatrixPacking(EmpColumnMajor), + defaultBlockStorage(EbsShared), diagnostics(is), - directiveHandler(ext, diagnostics), + shaderVersion(100), + directiveHandler(ext, diagnostics, shaderVersion), preprocessor(&diagnostics, &directiveHandler), scanner(NULL) { } TIntermediate& intermediate; // to hold and build a parse tree TSymbolTable& symbolTable; // symbol table that goes with the language currently being parsed - ShShaderType shaderType; // vertex or fragment language (future: pack or unpack) + sh::GLenum shaderType; // vertex or fragment language (future: pack or unpack) ShShaderSpec shaderSpec; // The language specification compiler conforms to - GLES2 or WebGL. + int shaderVersion; int compileOptions; const char* sourcePath; // Path of source file or NULL. TIntermNode* treeRoot; // root of parse tree being created @@ -55,12 +59,15 @@ struct TParseContext { bool functionReturnsValue; // true if a non-void function has a return bool checksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit. bool fragmentPrecisionHigh; // true if highp precision is supported in the fragment language. + TLayoutMatrixPacking defaultMatrixPacking; + TLayoutBlockStorage defaultBlockStorage; TString HashErrMsg; TDiagnostics diagnostics; TDirectiveHandler directiveHandler; pp::Preprocessor preprocessor; void* scanner; + int getShaderVersion() const { return shaderVersion; } int numErrors() const { return diagnostics.numErrors(); } TInfoSink& infoSink() { return diagnostics.infoSink(); } void error(const TSourceLoc& loc, const char *reason, const char* token, @@ -71,7 +78,7 @@ struct TParseContext { void recover(); bool parseVectorFields(const TString&, int vecSize, TVectorFields&, const TSourceLoc& line); - bool parseMatrixFields(const TString&, int matSize, TMatrixFields&, const TSourceLoc& line); + bool parseMatrixFields(const TString&, int matCols, int matRows, TMatrixFields&, const TSourceLoc& line); bool reservedErrorCheck(const TSourceLoc& line, const TString& identifier); void assignError(const TSourceLoc& line, const char* op, TString left, TString right); @@ -86,38 +93,64 @@ struct TParseContext { bool arraySizeErrorCheck(const TSourceLoc& line, TIntermTyped* expr, int& size); bool arrayQualifierErrorCheck(const TSourceLoc& line, TPublicType type); bool arrayTypeErrorCheck(const TSourceLoc& line, TPublicType type); - bool arrayErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType type, TVariable*& variable); + bool arrayErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType &type, TVariable*& variable); bool voidErrorCheck(const TSourceLoc&, const TString&, const TPublicType&); bool boolErrorCheck(const TSourceLoc&, const TIntermTyped*); bool boolErrorCheck(const TSourceLoc&, const TPublicType&); bool samplerErrorCheck(const TSourceLoc& line, const TPublicType& pType, const char* reason); bool structQualifierErrorCheck(const TSourceLoc& line, const TPublicType& pType); + bool locationDeclaratorListCheck(const TSourceLoc& line, const TPublicType &pType); bool parameterSamplerErrorCheck(const TSourceLoc& line, TQualifier qualifier, const TType& type); - bool nonInitConstErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, bool array); - bool nonInitErrorCheck(const TSourceLoc& line, TString& identifier, TPublicType& type, TVariable*& variable); + bool nonInitConstErrorCheck(const TSourceLoc& line, const TString& identifier, TPublicType& type, bool array); + bool nonInitErrorCheck(const TSourceLoc& line, const TString& identifier, const TPublicType& type, TVariable*& variable); bool paramErrorCheck(const TSourceLoc& line, TQualifier qualifier, TQualifier paramQualifier, TType* type); bool extensionErrorCheck(const TSourceLoc& line, const TString&); + bool singleDeclarationErrorCheck(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier); + bool layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier); const TPragma& pragma() const { return directiveHandler.pragma(); } const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); } bool supportsExtension(const char* extension); bool isExtensionEnabled(const char* extension) const; + void handleExtensionDirective(const TSourceLoc& loc, const char* extName, const char* behavior); + void handlePragmaDirective(const TSourceLoc& loc, const char* name, const char* value); bool containsSampler(TType& type); bool areAllChildConst(TIntermAggregate* aggrNode); - const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, bool *builtIn = 0); - bool executeInitializer(const TSourceLoc& line, TString& identifier, TPublicType& pType, + const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, int shaderVersion, bool *builtIn = 0); + bool executeInitializer(const TSourceLoc& line, const TString& identifier, TPublicType& pType, TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0); + TPublicType addFullySpecifiedType(TQualifier qualifier, const TPublicType& typeSpecifier); + TPublicType addFullySpecifiedType(TQualifier qualifier, TLayoutQualifier layoutQualifier, const TPublicType& typeSpecifier); + 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* 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); + void parseGlobalLayoutQualifier(const TPublicType &typeQualifier); + TFunction *addConstructorFunc(TPublicType publicType); TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&); TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type); - TIntermTyped* constructStruct(TIntermNode*, TType*, int, const TSourceLoc&, bool subset); - TIntermTyped* constructBuiltIn(const TType*, TOperator, TIntermNode*, const TSourceLoc&, bool subset); TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&); TIntermTyped* addConstMatrixNode(int , TIntermTyped*, const TSourceLoc&); TIntermTyped* addConstArrayNode(int index, TIntermTyped* node, const TSourceLoc& line); - TIntermTyped* addConstStruct(TString& , TIntermTyped*, const TSourceLoc&); + TIntermTyped* addConstStruct(const TString &identifier, TIntermTyped *node, const TSourceLoc& line); TIntermTyped* addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc& location, TIntermTyped *indexExpression); + TIntermTyped* addFieldSelectionExpression(TIntermTyped *baseExpression, const TSourceLoc& dotLocation, const TString &fieldString, const TSourceLoc& fieldLocation); + + TFieldList *addStructDeclaratorList(const TPublicType& typeSpecifier, TFieldList *fieldList); + TPublicType addStructure(const TSourceLoc& structLine, const TSourceLoc& nameLine, const TString *structName, TFieldList* fieldList); + + TIntermAggregate* addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList, + const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine); + + TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine); + TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine); + TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier); + TPublicType joinInterpolationQualifiers(const TSourceLoc &interpolationLoc, TQualifier interpolationQualifier, + const TSourceLoc &storageLoc, TQualifier storageQualifier); // Performs an error check for embedded struct declarations. // Returns true if an error was raised due to the declaration of diff --git a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp index abe70262f2..887cb66504 100644 --- a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp +++ b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.cpp @@ -6,43 +6,44 @@ #include "compiler/translator/PoolAlloc.h" -#ifndef _MSC_VER -#include -#endif -#include +#include "compiler/translator/InitializeGlobals.h" +#include "common/platform.h" #include "common/angleutils.h" -#include "compiler/translator/InitializeGlobals.h" -#include "compiler/translator/osinclude.h" +#include "common/tls.h" + +#include +#include +#include -OS_TLSIndex PoolIndex = OS_INVALID_TLS_INDEX; +TLSIndex PoolIndex = TLS_INVALID_INDEX; bool InitializePoolIndex() { - assert(PoolIndex == OS_INVALID_TLS_INDEX); + assert(PoolIndex == TLS_INVALID_INDEX); - PoolIndex = OS_AllocTLSIndex(); - return PoolIndex != OS_INVALID_TLS_INDEX; + PoolIndex = CreateTLSIndex(); + return PoolIndex != TLS_INVALID_INDEX; } void FreePoolIndex() { - assert(PoolIndex != OS_INVALID_TLS_INDEX); + assert(PoolIndex != TLS_INVALID_INDEX); - OS_FreeTLSIndex(PoolIndex); - PoolIndex = OS_INVALID_TLS_INDEX; + DestroyTLSIndex(PoolIndex); + PoolIndex = TLS_INVALID_INDEX; } TPoolAllocator* GetGlobalPoolAllocator() { - assert(PoolIndex != OS_INVALID_TLS_INDEX); - return static_cast(OS_GetTLSValue(PoolIndex)); + assert(PoolIndex != TLS_INVALID_INDEX); + return static_cast(GetTLSValue(PoolIndex)); } void SetGlobalPoolAllocator(TPoolAllocator* poolAllocator) { - assert(PoolIndex != OS_INVALID_TLS_INDEX); - OS_SetTLSValue(PoolIndex, poolAllocator); + assert(PoolIndex != TLS_INVALID_INDEX); + SetTLSValue(PoolIndex, poolAllocator); } // diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp index 92e5dbbfe1..e381c32690 100644 --- a/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp +++ b/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp @@ -8,70 +8,22 @@ #include "compiler/translator/RemoveTree.h" // -// Code to recursively delete the intermediate tree. +// Code to delete the intermediate tree. // - -class RemoveTree : public TIntermTraverser -{ -public: - RemoveTree() : TIntermTraverser(false, false, true) - { - } - -protected: - void visitSymbol(TIntermSymbol*); - void visitConstantUnion(TIntermConstantUnion*); - bool visitBinary(Visit visit, TIntermBinary*); - bool visitUnary(Visit visit, TIntermUnary*); - bool visitSelection(Visit visit, TIntermSelection*); - bool visitAggregate(Visit visit, TIntermAggregate*); -}; - -void RemoveTree::visitSymbol(TIntermSymbol* node) -{ - delete node; -} - -bool RemoveTree::visitBinary(Visit visit, TIntermBinary* node) -{ - delete node; - - return true; -} - -bool RemoveTree::visitUnary(Visit visit, TIntermUnary* node) -{ - delete node; - - return true; -} - -bool RemoveTree::visitAggregate(Visit visit, TIntermAggregate* node) +void RemoveAllTreeNodes(TIntermNode* root) { - delete node; + std::queue nodeQueue; - return true; -} + nodeQueue.push(root); -bool RemoveTree::visitSelection(Visit visit, TIntermSelection* node) -{ - delete node; + while (!nodeQueue.empty()) + { + TIntermNode *node = nodeQueue.front(); + nodeQueue.pop(); - return true; -} - -void RemoveTree::visitConstantUnion(TIntermConstantUnion* node) -{ - delete node; -} - -// -// Entry point. -// -void RemoveAllTreeNodes(TIntermNode* root) -{ - RemoveTree it; + node->enqueueChildren(&nodeQueue); - root->traverse(&it); + delete node; + } } diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp index 48e87cd57a..b03beb5c6c 100644 --- a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp +++ b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.cpp @@ -14,6 +14,24 @@ namespace sh { +namespace +{ + +class ElseBlockRewriter : public TIntermTraverser +{ + public: + ElseBlockRewriter(); + + protected: + bool visitAggregate(Visit visit, TIntermAggregate *aggregate); + + private: + int mTemporaryIndex; + const TType *mFunctionType; + + TIntermNode *rewriteSelection(TIntermSelection *selection); +}; + TIntermSymbol *MakeNewTemporary(const TString &name, TBasicType type) { TType variableType(type, EbpHigh, EvqInternal); @@ -36,25 +54,45 @@ TIntermUnary *MakeNewUnary(TOperator op, TIntermTyped *operand) return unary; } +ElseBlockRewriter::ElseBlockRewriter() + : TIntermTraverser(true, false, true, false), + mTemporaryIndex(0), + mFunctionType(NULL) +{} + bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node) { switch (node->getOp()) { case EOpSequence: + if (visit == PostVisit) { - for (size_t statementIndex = 0; statementIndex != node->getSequence().size(); statementIndex++) + for (size_t statementIndex = 0; statementIndex != node->getSequence()->size(); statementIndex++) { - TIntermNode *statement = node->getSequence()[statementIndex]; + TIntermNode *statement = (*node->getSequence())[statementIndex]; TIntermSelection *selection = statement->getAsSelectionNode(); if (selection && selection->getFalseBlock() != NULL) { - node->getSequence()[statementIndex] = rewriteSelection(selection); + // Check for if / else if + TIntermSelection *elseIfBranch = selection->getFalseBlock()->getAsSelectionNode(); + if (elseIfBranch) + { + selection->replaceChildNode(elseIfBranch, rewriteSelection(elseIfBranch)); + delete elseIfBranch; + } + + (*node->getSequence())[statementIndex] = rewriteSelection(selection); delete selection; } } } break; + case EOpFunction: + // Store the current function context (see comment below) + mFunctionType = ((visit == PreVisit) ? &node->getType() : NULL); + break; + default: break; } @@ -63,32 +101,54 @@ bool ElseBlockRewriter::visitAggregate(Visit visit, TIntermAggregate *node) TIntermNode *ElseBlockRewriter::rewriteSelection(TIntermSelection *selection) { - ASSERT(selection->getFalseBlock() != NULL); + ASSERT(selection != NULL); TString temporaryName = "cond_" + str(mTemporaryIndex++); TIntermTyped *typedCondition = selection->getCondition()->getAsTyped(); TType resultType(EbtBool, EbpUndefined); - TIntermSymbol *conditionSymbolA = MakeNewTemporary(temporaryName, EbtBool); - TIntermSymbol *conditionSymbolB = MakeNewTemporary(temporaryName, EbtBool); - TIntermSymbol *conditionSymbolC = MakeNewTemporary(temporaryName, EbtBool); - TIntermBinary *storeCondition = MakeNewBinary(EOpInitialize, conditionSymbolA, + TIntermSymbol *conditionSymbolInit = MakeNewTemporary(temporaryName, EbtBool); + TIntermBinary *storeCondition = MakeNewBinary(EOpInitialize, conditionSymbolInit, typedCondition, resultType); - TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolB); - TIntermSelection *falseBlock = new TIntermSelection(negatedCondition, - selection->getFalseBlock(), NULL); - TIntermSelection *newIfElse = new TIntermSelection(conditionSymbolC, - selection->getTrueBlock(), falseBlock); + TIntermNode *negatedElse = NULL; + + TIntermSelection *falseBlock = NULL; + + if (selection->getFalseBlock()) + { + // crbug.com/346463 + // D3D generates error messages claiming a function has no return value, when rewriting + // an if-else clause that returns something non-void in a function. By appending dummy + // returns (that are unreachable) we can silence this compile error. + if (mFunctionType && mFunctionType->getBasicType() != EbtVoid) + { + TString typeString = mFunctionType->getStruct() ? mFunctionType->getStruct()->name() : + mFunctionType->getBasicString(); + TString rawText = "return (" + typeString + ")0"; + negatedElse = new TIntermRaw(*mFunctionType, rawText); + } + + TIntermSymbol *conditionSymbolElse = MakeNewTemporary(temporaryName, EbtBool); + TIntermUnary *negatedCondition = MakeNewUnary(EOpLogicalNot, conditionSymbolElse); + falseBlock = new TIntermSelection(negatedCondition, + selection->getFalseBlock(), negatedElse); + } + + TIntermSymbol *conditionSymbolSel = MakeNewTemporary(temporaryName, EbtBool); + TIntermSelection *newSelection = new TIntermSelection(conditionSymbolSel, + selection->getTrueBlock(), falseBlock); TIntermAggregate *declaration = new TIntermAggregate(EOpDeclaration); - declaration->getSequence().push_back(storeCondition); + declaration->getSequence()->push_back(storeCondition); TIntermAggregate *block = new TIntermAggregate(EOpSequence); - block->getSequence().push_back(declaration); - block->getSequence().push_back(newIfElse); + block->getSequence()->push_back(declaration); + block->getSequence()->push_back(newSelection); return block; } +} + void RewriteElseBlocks(TIntermNode *node) { ElseBlockRewriter rewriter; diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h index 10221335ce..39963d6a82 100644 --- a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h +++ b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h @@ -15,23 +15,6 @@ namespace sh { -class ElseBlockRewriter : public TIntermTraverser -{ - public: - ElseBlockRewriter() - : TIntermTraverser(false, false, true, false) - , mTemporaryIndex(0) - {} - - protected: - bool visitAggregate(Visit visit, TIntermAggregate *aggregate); - - private: - int mTemporaryIndex; - - TIntermNode *rewriteSelection(TIntermSelection *selection); -}; - void RewriteElseBlocks(TIntermNode *node); } diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp new file mode 100644 index 0000000000..3a179f7499 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp @@ -0,0 +1,266 @@ +// +// 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/ScalarizeVecAndMatConstructorArgs.h" +#include "compiler/translator/compilerdebug.h" + +#include + +#include "common/angleutils.h" + +namespace +{ + +bool ContainsMatrixNode(const TIntermSequence &sequence) +{ + for (size_t ii = 0; ii < sequence.size(); ++ii) + { + TIntermTyped *node = sequence[ii]->getAsTyped(); + if (node && node->isMatrix()) + return true; + } + return false; +} + +bool ContainsVectorNode(const TIntermSequence &sequence) +{ + for (size_t ii = 0; ii < sequence.size(); ++ii) + { + TIntermTyped *node = sequence[ii]->getAsTyped(); + if (node && node->isVector()) + return true; + } + return false; +} + +TIntermConstantUnion *ConstructIndexNode(int index) +{ + ConstantUnion *u = new ConstantUnion[1]; + u[0].setIConst(index); + + TType type(EbtInt, EbpUndefined, EvqConst, 1); + TIntermConstantUnion *node = new TIntermConstantUnion(u, type); + return node; +} + +TIntermBinary *ConstructVectorIndexBinaryNode(TIntermSymbol *symbolNode, int index) +{ + TIntermBinary *binary = new TIntermBinary(EOpIndexDirect); + binary->setLeft(symbolNode); + TIntermConstantUnion *indexNode = ConstructIndexNode(index); + binary->setRight(indexNode); + return binary; +} + +TIntermBinary *ConstructMatrixIndexBinaryNode( + TIntermSymbol *symbolNode, int colIndex, int rowIndex) +{ + TIntermBinary *colVectorNode = + ConstructVectorIndexBinaryNode(symbolNode, colIndex); + + TIntermBinary *binary = new TIntermBinary(EOpIndexDirect); + binary->setLeft(colVectorNode); + TIntermConstantUnion *rowIndexNode = ConstructIndexNode(rowIndex); + binary->setRight(rowIndexNode); + return binary; +} + +} // namespace anonymous + +bool ScalarizeVecAndMatConstructorArgs::visitAggregate(Visit visit, TIntermAggregate *node) +{ + if (visit == PreVisit) + { + switch (node->getOp()) + { + case EOpSequence: + mSequenceStack.push_back(TIntermSequence()); + { + for (TIntermSequence::const_iterator iter = node->getSequence()->begin(); + iter != node->getSequence()->end(); ++iter) + { + TIntermNode *child = *iter; + ASSERT(child != NULL); + child->traverse(this); + mSequenceStack.back().push_back(child); + } + } + if (mSequenceStack.back().size() > node->getSequence()->size()) + { + node->getSequence()->clear(); + *(node->getSequence()) = mSequenceStack.back(); + } + mSequenceStack.pop_back(); + return false; + case EOpConstructVec2: + case EOpConstructVec3: + case EOpConstructVec4: + case EOpConstructBVec2: + case EOpConstructBVec3: + case EOpConstructBVec4: + case EOpConstructIVec2: + case EOpConstructIVec3: + case EOpConstructIVec4: + if (ContainsMatrixNode(*(node->getSequence()))) + scalarizeArgs(node, false, true); + break; + case EOpConstructMat2: + case EOpConstructMat3: + case EOpConstructMat4: + if (ContainsVectorNode(*(node->getSequence()))) + scalarizeArgs(node, true, false); + break; + default: + break; + } + } + return true; +} + +void ScalarizeVecAndMatConstructorArgs::scalarizeArgs( + TIntermAggregate *aggregate, bool scalarizeVector, bool scalarizeMatrix) +{ + ASSERT(aggregate); + int size = 0; + switch (aggregate->getOp()) + { + case EOpConstructVec2: + case EOpConstructBVec2: + case EOpConstructIVec2: + size = 2; + break; + case EOpConstructVec3: + case EOpConstructBVec3: + case EOpConstructIVec3: + size = 3; + break; + case EOpConstructVec4: + case EOpConstructBVec4: + case EOpConstructIVec4: + case EOpConstructMat2: + size = 4; + break; + case EOpConstructMat3: + size = 9; + break; + case EOpConstructMat4: + size = 16; + break; + default: + break; + } + TIntermSequence *sequence = aggregate->getSequence(); + TIntermSequence original(*sequence); + sequence->clear(); + for (size_t ii = 0; ii < original.size(); ++ii) + { + ASSERT(size > 0); + TIntermTyped *node = original[ii]->getAsTyped(); + ASSERT(node); + TString varName = createTempVariable(node); + if (node->isScalar()) + { + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); + sequence->push_back(symbolNode); + size--; + } + else if (node->isVector()) + { + if (scalarizeVector) + { + int repeat = std::min(size, node->getNominalSize()); + size -= repeat; + for (int index = 0; index < repeat; ++index) + { + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); + TIntermBinary *newNode = ConstructVectorIndexBinaryNode( + symbolNode, index); + sequence->push_back(newNode); + } + } + else + { + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); + sequence->push_back(symbolNode); + size -= node->getNominalSize(); + } + } + else + { + ASSERT(node->isMatrix()); + if (scalarizeMatrix) + { + int colIndex = 0, rowIndex = 0; + int repeat = std::min(size, node->getCols() * node->getRows()); + size -= repeat; + while (repeat > 0) + { + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); + TIntermBinary *newNode = ConstructMatrixIndexBinaryNode( + symbolNode, colIndex, rowIndex); + sequence->push_back(newNode); + rowIndex++; + if (rowIndex >= node->getRows()) + { + rowIndex = 0; + colIndex++; + } + repeat--; + } + } + else + { + TIntermSymbol *symbolNode = + new TIntermSymbol(-1, varName, node->getType()); + sequence->push_back(symbolNode); + size -= node->getCols() * node->getRows(); + } + } + } +} + +TString ScalarizeVecAndMatConstructorArgs::createTempVariable(TIntermTyped *original) +{ + TString tempVarName = "_webgl_tmp_"; + if (original->isScalar()) + { + tempVarName += "scalar_"; + } + else if (original->isVector()) + { + tempVarName += "vec_"; + } + else + { + ASSERT(original->isMatrix()); + tempVarName += "mat_"; + } + tempVarName += Str(mTempVarCount).c_str(); + mTempVarCount++; + + ASSERT(original); + TType type = original->getType(); + type.setQualifier(EvqTemporary); + + TIntermBinary *init = new TIntermBinary(EOpInitialize); + TIntermSymbol *symbolNode = new TIntermSymbol(-1, tempVarName, type); + init->setLeft(symbolNode); + init->setRight(original); + init->setType(type); + + TIntermAggregate *decl = new TIntermAggregate(EOpDeclaration); + decl->getSequence()->push_back(init); + + ASSERT(mSequenceStack.size() > 0); + TIntermSequence &sequence = mSequenceStack.back(); + sequence.push_back(decl); + + return tempVarName; +} diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h new file mode 100644 index 0000000000..6aeb0c4f60 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h @@ -0,0 +1,41 @@ +// +// 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_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ +#define COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ + +#include "compiler/translator/intermediate.h" + +class ScalarizeVecAndMatConstructorArgs : public TIntermTraverser +{ + public: + ScalarizeVecAndMatConstructorArgs() + : mTempVarCount(0) {} + + protected: + virtual bool visitAggregate(Visit visit, TIntermAggregate *node); + + private: + void scalarizeArgs(TIntermAggregate *aggregate, + bool scalarizeVector, bool scalarizeMatrix); + + // If we have the following code: + // mat4 m(0); + // vec4 v(1, m); + // We will rewrite to: + // mat4 m(0); + // mat4 _webgl_tmp_mat_0 = m; + // vec4 v(1, _webgl_tmp_mat_0[0][0], _webgl_tmp_mat_0[0][1], _webgl_tmp_mat_0[0][2]); + // This function is to create nodes for "mat4 _webgl_tmp_mat_0 = m;" and insert it to + // the code sequence. + // Return the temporary variable name. + TString createTempVariable(TIntermTyped *original); + + std::vector mSequenceStack; + int mTempVarCount; +}; + +#endif // COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ShHandle.h b/src/3rdparty/angle/src/compiler/translator/ShHandle.h deleted file mode 100644 index 54ae27852d..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ShHandle.h +++ /dev/null @@ -1,179 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef _SHHANDLE_INCLUDED_ -#define _SHHANDLE_INCLUDED_ - -// -// Machine independent part of the compiler private objects -// sent as ShHandle to the driver. -// -// This should not be included by driver code. -// - -#include "GLSLANG/ShaderLang.h" - -#include "compiler/translator/BuiltInFunctionEmulator.h" -#include "compiler/translator/ExtensionBehavior.h" -#include "compiler/translator/HashNames.h" -#include "compiler/translator/InfoSink.h" -#include "compiler/translator/SymbolTable.h" -#include "compiler/translator/VariableInfo.h" -#include "third_party/compiler/ArrayBoundsClamper.h" - -class LongNameMap; -class TCompiler; -class TDependencyGraph; -class TranslatorHLSL; - -// -// Helper function to identify specs that are based on the WebGL spec, -// like the CSS Shaders spec. -// -bool isWebGLBasedSpec(ShShaderSpec spec); - -// -// The base class used to back handles returned to the driver. -// -class TShHandleBase { -public: - TShHandleBase(); - virtual ~TShHandleBase(); - virtual TCompiler* getAsCompiler() { return 0; } - virtual TranslatorHLSL* getAsTranslatorHLSL() { return 0; } - -protected: - // Memory allocator. Allocates and tracks memory required by the compiler. - // Deallocates all memory when compiler is destructed. - TPoolAllocator allocator; -}; - -// -// The base class for the machine dependent compiler to derive from -// for managing object code from the compile. -// -class TCompiler : public TShHandleBase { -public: - TCompiler(ShShaderType type, ShShaderSpec spec); - virtual ~TCompiler(); - virtual TCompiler* getAsCompiler() { return this; } - - bool Init(const ShBuiltInResources& resources); - bool compile(const char* const shaderStrings[], - size_t numStrings, - int compileOptions); - - // Get results of the last compilation. - TInfoSink& getInfoSink() { return infoSink; } - const TVariableInfoList& getAttribs() const { return attribs; } - const TVariableInfoList& getUniforms() const { return uniforms; } - const TVariableInfoList& getVaryings() const { return varyings; } - int getMappedNameMaxLength() const; - - ShHashFunction64 getHashFunction() const { return hashFunction; } - NameMap& getNameMap() { return nameMap; } - TSymbolTable& getSymbolTable() { return symbolTable; } - -protected: - ShShaderType getShaderType() const { return shaderType; } - ShShaderSpec getShaderSpec() const { return shaderSpec; } - // Initialize symbol-table with built-in symbols. - bool InitBuiltInSymbolTable(const ShBuiltInResources& resources); - // Clears the results from the previous compilation. - void clearResults(); - // Return true if function recursion is detected or call depth exceeded. - bool detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth); - // Rewrites a shader's intermediate tree according to the CSS Shaders spec. - void rewriteCSSShader(TIntermNode* root); - // Returns true if the given shader does not exceed the minimum - // functionality mandated in GLSL 1.0 spec Appendix A. - bool validateLimitations(TIntermNode* root); - // Collect info for all attribs, uniforms, varyings. - void collectVariables(TIntermNode* root); - // Map long variable names into shorter ones. - void mapLongVariableNames(TIntermNode* root); - // Translate to object code. - virtual void translate(TIntermNode* root) = 0; - // Returns true if, after applying the packing rules in the GLSL 1.017 spec - // Appendix A, section 7, the shader does not use too many uniforms. - bool enforcePackingRestrictions(); - // Insert statements to initialize varyings without static use in the beginning - // of main(). It is to work around a Mac driver where such varyings in a vertex - // shader may be optimized out incorrectly at compile time, causing a link failure. - // This function should only be applied to vertex shaders. - void initializeVaryingsWithoutStaticUse(TIntermNode* root); - // Insert gl_Position = vec4(0,0,0,0) to the beginning of main(). - // It is to work around a Linux driver bug where missing this causes compile failure - // while spec says it is allowed. - // This function should only be applied to vertex shaders. - void initializeGLPosition(TIntermNode* root); - // Returns true if the shader passes the restrictions that aim to prevent timing attacks. - bool enforceTimingRestrictions(TIntermNode* root, bool outputGraph); - // Returns true if the shader does not use samplers. - bool enforceVertexShaderTimingRestrictions(TIntermNode* root); - // Returns true if the shader does not use sampler dependent values to affect control - // flow or in operations whose time can depend on the input values. - bool enforceFragmentShaderTimingRestrictions(const TDependencyGraph& graph); - // Return true if the maximum expression complexity below the limit. - bool limitExpressionComplexity(TIntermNode* root); - // Get built-in extensions with default behavior. - const TExtensionBehavior& getExtensionBehavior() const; - // Get the resources set by InitBuiltInSymbolTable - const ShBuiltInResources& getResources() const; - - const ArrayBoundsClamper& getArrayBoundsClamper() const; - ShArrayIndexClampingStrategy getArrayIndexClampingStrategy() const; - const BuiltInFunctionEmulator& getBuiltInFunctionEmulator() const; - -private: - ShShaderType shaderType; - ShShaderSpec shaderSpec; - - int maxUniformVectors; - int maxExpressionComplexity; - int maxCallStackDepth; - - ShBuiltInResources compileResources; - - // Built-in symbol table for the given language, spec, and resources. - // It is preserved from compile-to-compile. - TSymbolTable symbolTable; - // Built-in extensions with default behavior. - TExtensionBehavior extensionBehavior; - bool fragmentPrecisionHigh; - - ArrayBoundsClamper arrayBoundsClamper; - ShArrayIndexClampingStrategy clampingStrategy; - BuiltInFunctionEmulator builtInFunctionEmulator; - - // Results of compilation. - TInfoSink infoSink; // Output sink. - TVariableInfoList attribs; // Active attributes in the compiled shader. - TVariableInfoList uniforms; // Active uniforms in the compiled shader. - TVariableInfoList varyings; // Varyings in the compiled shader. - - // Cached copy of the ref-counted singleton. - LongNameMap* longNameMap; - - // name hashing. - ShHashFunction64 hashFunction; - NameMap nameMap; -}; - -// -// This is the interface between the machine independent code -// and the machine dependent code. -// -// The machine dependent code should derive from the classes -// above. Then Construct*() and Delete*() will create and -// destroy the machine dependent objects, which contain the -// above machine independent information. -// -TCompiler* ConstructCompiler( - ShShaderType type, ShShaderSpec spec, ShShaderOutput output); -void DeleteCompiler(TCompiler*); - -#endif // _SHHANDLE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp index 608237860c..6a801eacfe 100644 --- a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -11,11 +11,14 @@ #include "GLSLANG/ShaderLang.h" +#include "compiler/translator/Compiler.h" #include "compiler/translator/InitializeDll.h" -#include "compiler/preprocessor/length_limits.h" -#include "compiler/translator/ShHandle.h" +#include "compiler/translator/length_limits.h" #include "compiler/translator/TranslatorHLSL.h" #include "compiler/translator/VariablePacker.h" +#include "angle_gl.h" + +static bool isInitialized = false; // // This is the platform independent interface between an OGL driver @@ -43,14 +46,62 @@ static bool checkMappedNameMaxLength(const ShHandle handle, size_t expectedValue return (expectedValue == mappedNameMaxLength); } +template +static const sh::ShaderVariable *ReturnVariable(const std::vector &infoList, int index) +{ + if (index < 0 || static_cast(index) >= infoList.size()) + { + return NULL; + } + + return &infoList[index]; +} + +static const sh::ShaderVariable *GetVariable(const TCompiler *compiler, ShShaderInfo varType, int index) +{ + switch (varType) + { + case SH_ACTIVE_ATTRIBUTES: + return ReturnVariable(compiler->getAttributes(), index); + case SH_ACTIVE_UNIFORMS: + return ReturnVariable(compiler->getExpandedUniforms(), index); + case SH_VARYINGS: + return ReturnVariable(compiler->getExpandedVaryings(), index); + default: + UNREACHABLE(); + return NULL; + } +} + +static ShPrecisionType ConvertPrecision(sh::GLenum precision) +{ + switch (precision) + { + case GL_HIGH_FLOAT: + case GL_HIGH_INT: + return SH_PRECISION_HIGHP; + case GL_MEDIUM_FLOAT: + case GL_MEDIUM_INT: + return SH_PRECISION_MEDIUMP; + case GL_LOW_FLOAT: + case GL_LOW_INT: + return SH_PRECISION_LOWP; + default: + return SH_PRECISION_UNDEFINED; + } +} + // // Driver must call this first, once, before doing any other compiler operations. // Subsequent calls to this function are no-op. // int ShInitialize() { - static const bool kInitialized = InitProcess(); - return kInitialized ? 1 : 0; + if (!isInitialized) + { + isInitialized = InitProcess(); + } + return isInitialized ? 1 : 0; } // @@ -58,7 +109,11 @@ int ShInitialize() // int ShFinalize() { - DetachProcess(); + if (isInitialized) + { + DetachProcess(); + isInitialized = false; + } return 1; } @@ -83,10 +138,17 @@ void ShInitBuiltInResources(ShBuiltInResources* resources) resources->ARB_texture_rectangle = 0; resources->EXT_draw_buffers = 0; resources->EXT_frag_depth = 0; + resources->EXT_shader_texture_lod = 0; // Disable highp precision in fragment shader by default. resources->FragmentPrecisionHigh = 0; + // GLSL ES 3.0 constants. + resources->MaxVertexOutputVectors = 16; + resources->MaxFragmentInputVectors = 15; + resources->MinProgramTexelOffset = -8; + resources->MaxProgramTexelOffset = 7; + // Disable name hashing by default. resources->HashFunction = NULL; @@ -99,7 +161,7 @@ void ShInitBuiltInResources(ShBuiltInResources* resources) // // Driver calls these to create and destroy compiler objects. // -ShHandle ShConstructCompiler(ShShaderType type, ShShaderSpec spec, +ShHandle ShConstructCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output, const ShBuiltInResources* resources) { @@ -128,8 +190,25 @@ void ShDestruct(ShHandle handle) DeleteCompiler(base->getAsCompiler()); } +void ShGetBuiltInResourcesString(const ShHandle handle, size_t outStringLen, char *outString) +{ + if (!handle || !outString) + { + return; + } + + TShHandleBase *base = static_cast(handle); + TCompiler *compiler = base->getAsCompiler(); + if (!compiler) + { + return; + } + + strncpy(outString, compiler->getBuiltInResourcesString().c_str(), outStringLen); + outString[outStringLen - 1] = '\0'; +} // -// Do an actual compile on the given strings. The result is left +// Do an actual compile on the given strings. The result is left // in the given compile object. // // Return: The return value of ShCompile is really boolean, indicating @@ -171,30 +250,30 @@ void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params) *params = compiler->getInfoSink().obj.size() + 1; break; case SH_ACTIVE_UNIFORMS: - *params = compiler->getUniforms().size(); + *params = compiler->getExpandedUniforms().size(); break; case SH_ACTIVE_UNIFORM_MAX_LENGTH: - *params = 1 + MAX_SYMBOL_NAME_LEN; + *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); break; case SH_ACTIVE_ATTRIBUTES: - *params = compiler->getAttribs().size(); + *params = compiler->getAttributes().size(); break; case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH: - *params = 1 + MAX_SYMBOL_NAME_LEN; + *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); break; case SH_VARYINGS: - *params = compiler->getVaryings().size(); + *params = compiler->getExpandedVaryings().size(); break; case SH_VARYING_MAX_LENGTH: - *params = 1 + MAX_SYMBOL_NAME_LEN; + *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); break; case SH_MAPPED_NAME_MAX_LENGTH: // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to // handle array and struct dereferences. - *params = 1 + MAX_SYMBOL_NAME_LEN; + *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); break; case SH_NAME_MAX_LENGTH: - *params = 1 + MAX_SYMBOL_NAME_LEN; + *params = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); break; case SH_HASHED_NAME_MAX_LENGTH: if (compiler->getHashFunction() == NULL) { @@ -203,12 +282,22 @@ void ShGetInfo(const ShHandle handle, ShShaderInfo pname, size_t* params) // 64 bits hashing output requires 16 bytes for hex // representation. const char HashedNamePrefix[] = HASHED_NAME_PREFIX; + (void)HashedNamePrefix; *params = 16 + sizeof(HashedNamePrefix); } break; case SH_HASHED_NAMES_COUNT: *params = compiler->getNameMap().size(); break; + case SH_SHADER_VERSION: + *params = compiler->getShaderVersion(); + break; + case SH_RESOURCES_STRING_LENGTH: + *params = compiler->getBuiltInResourcesString().length() + 1; + break; + case SH_OUTPUT_TYPE: + *params = compiler->getOutputType(); + break; default: UNREACHABLE(); } } @@ -250,7 +339,7 @@ void ShGetVariableInfo(const ShHandle handle, int index, size_t* length, int* size, - ShDataType* type, + sh::GLenum* type, ShPrecisionType* precision, int* staticUse, char* name, @@ -267,47 +356,32 @@ void ShGetVariableInfo(const ShHandle handle, if (compiler == 0) return; - const TVariableInfoList& varList = - varType == SH_ACTIVE_ATTRIBUTES ? compiler->getAttribs() : - (varType == SH_ACTIVE_UNIFORMS ? compiler->getUniforms() : - compiler->getVaryings()); - if (index < 0 || index >= static_cast(varList.size())) + const sh::ShaderVariable *varInfo = GetVariable(compiler, varType, index); + if (!varInfo) + { return; - - const TVariableInfo& varInfo = varList[index]; - if (length) *length = varInfo.name.size(); - *size = varInfo.size; - *type = varInfo.type; - switch (varInfo.precision) { - case EbpLow: - *precision = SH_PRECISION_LOWP; - break; - case EbpMedium: - *precision = SH_PRECISION_MEDIUMP; - break; - case EbpHigh: - *precision = SH_PRECISION_HIGHP; - break; - default: - // Some types does not support precision, for example, boolean. - *precision = SH_PRECISION_UNDEFINED; - break; } - *staticUse = varInfo.staticUse ? 1 : 0; + + if (length) *length = varInfo->name.size(); + *size = varInfo->elementCount(); + *type = varInfo->type; + *precision = ConvertPrecision(varInfo->precision); + *staticUse = varInfo->staticUse ? 1 : 0; // This size must match that queried by // SH_ACTIVE_UNIFORM_MAX_LENGTH, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, SH_VARYING_MAX_LENGTH // in ShGetInfo, below. - size_t variableLength = 1 + MAX_SYMBOL_NAME_LEN; + size_t variableLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); ASSERT(checkVariableMaxLengths(handle, variableLength)); - strncpy(name, varInfo.name.c_str(), variableLength); + strncpy(name, varInfo->name.c_str(), variableLength); name[variableLength - 1] = 0; - if (mappedName) { + if (mappedName) + { // This size must match that queried by // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below. - size_t maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN; + size_t maxMappedNameLength = 1 + GetGlobalMaxTokenSize(compiler->getShaderSpec()); ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength)); - strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength); + strncpy(mappedName, varInfo->mappedName.c_str(), maxMappedNameLength); mappedName[maxMappedNameLength - 1] = 0; } } @@ -369,6 +443,18 @@ void ShGetInfoPointer(const ShHandle handle, ShShaderInfo pname, void** params) 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(); } } @@ -379,12 +465,62 @@ int ShCheckVariablesWithinPackingLimits( if (varInfoArraySize == 0) return 1; ASSERT(varInfoArray); - TVariableInfoList variables; + std::vector variables; for (size_t ii = 0; ii < varInfoArraySize; ++ii) { - TVariableInfo var(varInfoArray[ii].type, varInfoArray[ii].size); + sh::ShaderVariable var(varInfoArray[ii].type, (sh::GLenum)0, "", varInfoArray[ii].size); variables.push_back(var); } VariablePacker packer; return packer.CheckVariablesWithinPackingLimits(maxVectors, variables) ? 1 : 0; } + +bool ShGetInterfaceBlockRegister(const ShHandle handle, + const char *interfaceBlockName, + unsigned int *indexOut) +{ + if (!handle || !interfaceBlockName || !indexOut) + { + return false; + } + + TShHandleBase* base = static_cast(handle); + TranslatorHLSL* translator = base->getAsTranslatorHLSL(); + if (!translator) + { + return false; + } + + if (!translator->hasInterfaceBlock(interfaceBlockName)) + { + return false; + } + + *indexOut = translator->getInterfaceBlockRegister(interfaceBlockName); + return true; +} + +bool ShGetUniformRegister(const ShHandle handle, + const char *uniformName, + unsigned int *indexOut) +{ + if (!handle || !uniformName || !indexOut) + { + return false; + } + + TShHandleBase* base = static_cast(handle); + TranslatorHLSL* translator = base->getAsTranslatorHLSL(); + if (!translator) + { + return false; + } + + if (!translator->hasUniform(uniformName)) + { + return false; + } + + *indexOut = translator->getUniformRegister(uniformName); + return true; +} diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp new file mode 100644 index 0000000000..365985c852 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp @@ -0,0 +1,477 @@ +// +// 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. +// +// StructureHLSL.cpp: +// Definitions of methods for HLSL translation of GLSL structures. +// + +#include "compiler/translator/StructureHLSL.h" +#include "common/utilities.h" +#include "compiler/translator/OutputHLSL.h" +#include "compiler/translator/Types.h" +#include "compiler/translator/util.h" +#include "compiler/translator/UtilsHLSL.h" + +namespace sh +{ + +Std140PaddingHelper::Std140PaddingHelper(const std::map &structElementIndexes) + : mPaddingCounter(0), + mElementIndex(0), + mStructElementIndexes(structElementIndexes) +{} + +int Std140PaddingHelper::prePadding(const TType &type) +{ + if (type.getBasicType() == EbtStruct || type.isMatrix() || type.isArray()) + { + // no padding needed, HLSL will align the field to a new register + mElementIndex = 0; + return 0; + } + + const GLenum glType = GLVariableType(type); + const int numComponents = gl::VariableComponentCount(glType); + + if (numComponents >= 4) + { + // no padding needed, HLSL will align the field to a new register + mElementIndex = 0; + return 0; + } + + if (mElementIndex + numComponents > 4) + { + // no padding needed, HLSL will align the field to a new register + mElementIndex = numComponents; + return 0; + } + + const int alignment = numComponents == 3 ? 4 : numComponents; + const int paddingOffset = (mElementIndex % alignment); + const int paddingCount = (paddingOffset != 0 ? (alignment - paddingOffset) : 0); + + mElementIndex += paddingCount; + mElementIndex += numComponents; + mElementIndex %= 4; + + return paddingCount; +} + +TString Std140PaddingHelper::prePaddingString(const TType &type) +{ + int paddingCount = prePadding(type); + + TString padding; + + for (int paddingIndex = 0; paddingIndex < paddingCount; paddingIndex++) + { + padding += " float pad_" + str(mPaddingCounter++) + ";\n"; + } + + return padding; +} + +TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRowMajorPacking) +{ + if (!type.isMatrix() && !type.isArray() && type.getBasicType() != EbtStruct) + { + return ""; + } + + int numComponents = 0; + TStructure *structure = type.getStruct(); + + if (type.isMatrix()) + { + // This method can also be called from structureString, which does not use layout qualifiers. + // Thus, use the method parameter for determining the matrix packing. + // + // Note HLSL row major packing corresponds to GL API column-major, and vice-versa, since we + // wish to always transpose GL matrices to play well with HLSL's matrix array indexing. + // + const bool isRowMajorMatrix = !useHLSLRowMajorPacking; + const GLenum glType = GLVariableType(type); + numComponents = gl::MatrixComponentCount(glType, isRowMajorMatrix); + } + else if (structure) + { + const TString &structName = QualifiedStructNameString(*structure, + useHLSLRowMajorPacking, true); + numComponents = mStructElementIndexes.find(structName)->second; + + if (numComponents == 0) + { + return ""; + } + } + else + { + const GLenum glType = GLVariableType(type); + numComponents = gl::VariableComponentCount(glType); + } + + TString padding; + for (int paddingOffset = numComponents; paddingOffset < 4; paddingOffset++) + { + padding += " float pad_" + str(mPaddingCounter++) + ";\n"; + } + return padding; +} + +StructureHLSL::StructureHLSL() +{} + +TString StructureHLSL::defineQualified(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing) +{ + if (useStd140Packing) + { + Std140PaddingHelper padHelper(mStd140StructElementIndexes); + return define(structure, useHLSLRowMajorPacking, useStd140Packing, &padHelper); + } + else + { + return define(structure, useHLSLRowMajorPacking, useStd140Packing, NULL); + } +} + +TString StructureHLSL::defineNameless(const TStructure &structure) +{ + return define(structure, false, false, NULL); +} + +TString StructureHLSL::define(const TStructure &structure, bool useHLSLRowMajorPacking, + bool useStd140Packing, Std140PaddingHelper *padHelper) +{ + const TFieldList &fields = structure.fields(); + const bool isNameless = (structure.name() == ""); + const TString &structName = QualifiedStructNameString(structure, useHLSLRowMajorPacking, + useStd140Packing); + const TString declareString = (isNameless ? "struct" : "struct " + structName); + + TString string; + string += declareString + "\n" + "{\n"; + + for (unsigned int i = 0; i < fields.size(); i++) + { + const TField &field = *fields[i]; + const TType &fieldType = *field.type(); + const TStructure *fieldStruct = fieldType.getStruct(); + const TString &fieldTypeString = fieldStruct ? + QualifiedStructNameString(*fieldStruct, useHLSLRowMajorPacking, + useStd140Packing) : + TypeString(fieldType); + + if (padHelper) + { + string += padHelper->prePaddingString(fieldType); + } + + string += " " + fieldTypeString + " " + DecorateField(field.name(), structure) + ArrayString(fieldType) + ";\n"; + + if (padHelper) + { + string += padHelper->postPaddingString(fieldType, useHLSLRowMajorPacking); + } + } + + // Nameless structs do not finish with a semicolon and newline, to leave room for an instance variable + string += (isNameless ? "} " : "};\n"); + + return string; +} + +void StructureHLSL::addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters) +{ + if (name == "") + { + return; // Nameless structures don't have constructors + } + + if (type.getStruct() && mStructNames.find(name) != mStructNames.end()) + { + return; // Already added + } + + TType ctorType = type; + ctorType.clearArrayness(); + ctorType.setPrecision(EbpHigh); + ctorType.setQualifier(EvqTemporary); + + typedef std::vector ParameterArray; + ParameterArray ctorParameters; + + const TStructure* structure = type.getStruct(); + if (structure) + { + mStructNames.insert(name); + + // Add element index + storeStd140ElementIndex(*structure, false); + storeStd140ElementIndex(*structure, true); + + const TString &structString = defineQualified(*structure, false, false); + + if (std::find(mStructDeclarations.begin(), mStructDeclarations.end(), structString) == mStructDeclarations.end()) + { + // Add row-major packed struct for interface blocks + TString rowMajorString = "#pragma pack_matrix(row_major)\n" + + defineQualified(*structure, true, false) + + "#pragma pack_matrix(column_major)\n"; + + TString std140String = defineQualified(*structure, false, true); + TString std140RowMajorString = "#pragma pack_matrix(row_major)\n" + + defineQualified(*structure, true, true) + + "#pragma pack_matrix(column_major)\n"; + + mStructDeclarations.push_back(structString); + mStructDeclarations.push_back(rowMajorString); + mStructDeclarations.push_back(std140String); + mStructDeclarations.push_back(std140RowMajorString); + } + + const TFieldList &fields = structure->fields(); + for (unsigned int i = 0; i < fields.size(); i++) + { + ctorParameters.push_back(*fields[i]->type()); + } + } + else if (parameters) + { + for (TIntermSequence::const_iterator parameter = parameters->begin(); parameter != parameters->end(); parameter++) + { + ctorParameters.push_back((*parameter)->getAsTyped()->getType()); + } + } + else UNREACHABLE(); + + TString constructor; + + if (ctorType.getStruct()) + { + constructor += name + " " + name + "_ctor("; + } + else // Built-in type + { + constructor += TypeString(ctorType) + " " + name + "("; + } + + for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++) + { + const TType &type = ctorParameters[parameter]; + + constructor += TypeString(type) + " x" + str(parameter) + ArrayString(type); + + if (parameter < ctorParameters.size() - 1) + { + constructor += ", "; + } + } + + constructor += ")\n" + "{\n"; + + if (ctorType.getStruct()) + { + constructor += " " + name + " structure = {"; + } + else + { + constructor += " return " + TypeString(ctorType) + "("; + } + + if (ctorType.isMatrix() && ctorParameters.size() == 1) + { + int rows = ctorType.getRows(); + int cols = ctorType.getCols(); + const TType ¶meter = ctorParameters[0]; + + if (parameter.isScalar()) + { + for (int row = 0; row < rows; row++) + { + for (int col = 0; col < cols; col++) + { + constructor += TString((row == col) ? "x0" : "0.0"); + + if (row < rows - 1 || col < cols - 1) + { + constructor += ", "; + } + } + } + } + else if (parameter.isMatrix()) + { + for (int row = 0; row < rows; row++) + { + for (int col = 0; col < cols; col++) + { + if (row < parameter.getRows() && col < parameter.getCols()) + { + constructor += TString("x0") + "[" + str(row) + "][" + str(col) + "]"; + } + else + { + constructor += TString((row == col) ? "1.0" : "0.0"); + } + + if (row < rows - 1 || col < cols - 1) + { + constructor += ", "; + } + } + } + } + else + { + ASSERT(rows == 2 && cols == 2 && parameter.isVector() && parameter.getNominalSize() == 4); + + constructor += "x0"; + } + } + else + { + size_t remainingComponents = ctorType.getObjectSize(); + size_t parameterIndex = 0; + + while (remainingComponents > 0) + { + const TType ¶meter = ctorParameters[parameterIndex]; + const size_t parameterSize = parameter.getObjectSize(); + bool moreParameters = parameterIndex + 1 < ctorParameters.size(); + + constructor += "x" + str(parameterIndex); + + if (ctorType.getStruct()) + { + ASSERT(remainingComponents == parameterSize || moreParameters); + ASSERT(parameterSize <= remainingComponents); + + remainingComponents -= parameterSize; + } + else if (parameter.isScalar()) + { + remainingComponents -= parameter.getObjectSize(); + } + else if (parameter.isVector()) + { + if (remainingComponents == parameterSize || moreParameters) + { + ASSERT(parameterSize <= remainingComponents); + remainingComponents -= parameterSize; + } + else if (remainingComponents < static_cast(parameter.getNominalSize())) + { + switch (remainingComponents) + { + case 1: constructor += ".x"; break; + case 2: constructor += ".xy"; break; + case 3: constructor += ".xyz"; break; + case 4: constructor += ".xyzw"; break; + default: UNREACHABLE(); + } + + remainingComponents = 0; + } + else UNREACHABLE(); + } + else if (parameter.isMatrix()) + { + int column = 0; + while (remainingComponents > 0 && column < parameter.getCols()) + { + constructor += "[" + str(column) + "]"; + + if (remainingComponents < static_cast(parameter.getRows())) + { + switch (remainingComponents) + { + case 1: constructor += ".x"; break; + case 2: constructor += ".xy"; break; + case 3: constructor += ".xyz"; break; + default: UNREACHABLE(); + } + + remainingComponents = 0; + } + else + { + remainingComponents -= parameter.getRows(); + + if (remainingComponents > 0) + { + constructor += ", x" + str(parameterIndex); + } + } + + column++; + } + } + else UNREACHABLE(); + + if (moreParameters) + { + parameterIndex++; + } + + if (remainingComponents) + { + constructor += ", "; + } + } + } + + if (ctorType.getStruct()) + { + constructor += "};\n" + " return structure;\n" + "}\n"; + } + else + { + constructor += ");\n" + "}\n"; + } + + mConstructors.insert(constructor); +} + +std::string StructureHLSL::structsHeader() const +{ + TInfoSinkBase out; + + for (size_t structIndex = 0; structIndex < mStructDeclarations.size(); structIndex++) + { + out << mStructDeclarations[structIndex]; + } + + for (Constructors::const_iterator constructor = mConstructors.begin(); + constructor != mConstructors.end(); + constructor++) + { + out << *constructor; + } + + return out.str(); +} + +void StructureHLSL::storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking) +{ + Std140PaddingHelper padHelper(mStd140StructElementIndexes); + const TFieldList &fields = structure.fields(); + + for (unsigned int i = 0; i < fields.size(); i++) + { + padHelper.prePadding(*fields[i]->type()); + } + + // Add remaining element index to the global map, for use with nested structs in standard layouts + const TString &structName = QualifiedStructNameString(structure, useHLSLRowMajorPacking, true); + mStd140StructElementIndexes[structName] = padHelper.elementIndex(); +} + +} diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h new file mode 100644 index 0000000000..63fbaaaf8e --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h @@ -0,0 +1,74 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// StructureHLSL.h: +// Interfaces of methods for HLSL translation of GLSL structures. +// + +#ifndef TRANSLATOR_STRUCTUREHLSL_H_ +#define TRANSLATOR_STRUCTUREHLSL_H_ + +#include "compiler/translator/Common.h" +#include "compiler/translator/intermediate.h" + +#include + +class TInfoSinkBase; +class TScopeBracket; + +namespace sh +{ + +// This helper class assists structure and interface block definitions in determining +// how to pack std140 structs within HLSL's packing rules. +class Std140PaddingHelper +{ + public: + explicit Std140PaddingHelper(const std::map &structElementIndexes); + + int elementIndex() const { return mElementIndex; } + int prePadding(const TType &type); + TString prePaddingString(const TType &type); + TString postPaddingString(const TType &type, bool useHLSLRowMajorPacking); + + private: + int mPaddingCounter; + int mElementIndex; + const std::map &mStructElementIndexes; +}; + +class StructureHLSL +{ + public: + StructureHLSL(); + + void addConstructor(const TType &type, const TString &name, const TIntermSequence *parameters); + std::string structsHeader() const; + + TString defineQualified(const TStructure &structure, bool useHLSLRowMajorPacking, bool useStd140Packing); + static TString defineNameless(const TStructure &structure); + + Std140PaddingHelper getPaddingHelper() const { return Std140PaddingHelper(mStd140StructElementIndexes); } + + private: + std::map mStd140StructElementIndexes; + + typedef std::set StructNames; + StructNames mStructNames; + + typedef std::set Constructors; + Constructors mConstructors; + + typedef std::vector StructDeclarations; + StructDeclarations mStructDeclarations; + + void storeStd140ElementIndex(const TStructure &structure, bool useHLSLRowMajorPacking); + static TString define(const TStructure &structure, bool useHLSLRowMajorPacking, + bool useStd140Packing, Std140PaddingHelper *padHelper); +}; + +} + +#endif // COMPILER_STRUCTUREHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp index d04fe5d355..ae4fcaa6c3 100644 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -17,200 +17,220 @@ #include #include -#include -TType::TType(const TPublicType &p) : - type(p.type), precision(p.precision), qualifier(p.qualifier), size(p.size), matrix(p.matrix), array(p.array), arraySize(p.arraySize), structure(0) +int TSymbolTable::uniqueIdCounter = 0; + +// +// Functions have buried pointers to delete. +// +TFunction::~TFunction() { - if (p.userDef) - structure = p.userDef->getStruct(); + for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i) + delete (*i).type; } // -// Recursively generate mangled names. +// Symbol table levels are a map of pointers to symbols that have to be deleted. // -TString TType::buildMangledName() const +TSymbolTableLevel::~TSymbolTableLevel() { - TString mangledName; - if (isMatrix()) - mangledName += 'm'; - else if (isVector()) - mangledName += 'v'; - - switch (type) { - case EbtFloat: mangledName += 'f'; break; - case EbtInt: mangledName += 'i'; break; - case EbtBool: mangledName += 'b'; break; - case EbtSampler2D: mangledName += "s2"; break; - case EbtSamplerCube: mangledName += "sC"; break; - case EbtStruct: mangledName += structure->mangledName(); break; - default: break; - } - - mangledName += static_cast('0' + getNominalSize()); - if (isArray()) { - char buf[20]; - snprintf(buf, sizeof(buf), "%d", arraySize); - mangledName += '['; - mangledName += buf; - mangledName += ']'; - } - return mangledName; + for (tLevel::iterator it = level.begin(); it != level.end(); ++it) + delete (*it).second; } -size_t TType::getObjectSize() const +bool TSymbolTableLevel::insert(TSymbol *symbol) { - size_t totalSize = 0; + symbol->setUniqueId(TSymbolTable::nextUniqueId()); - if (getBasicType() == EbtStruct) - totalSize = structure->objectSize(); - else if (matrix) - totalSize = size * size; - else - totalSize = size; - - if (isArray()) { - size_t arraySize = getArraySize(); - if (arraySize > INT_MAX / totalSize) - totalSize = INT_MAX; - else - totalSize *= arraySize; - } + // returning true means symbol was added to the table + tInsertResult result = level.insert(tLevelPair(symbol->getMangledName(), symbol)); - return totalSize; + return result.second; } -bool TStructure::containsArrays() const +TSymbol *TSymbolTableLevel::find(const TString &name) const { - for (size_t i = 0; i < mFields->size(); ++i) { - const TType* fieldType = (*mFields)[i]->type(); - if (fieldType->isArray() || fieldType->isStructureContainingArrays()) - return true; - } - return false; + tLevel::const_iterator it = level.find(name); + if (it == level.end()) + return 0; + else + return (*it).second; } -TString TStructure::buildMangledName() const +// +// Change all function entries in the table with the non-mangled name +// to be related to the provided built-in operation. This is a low +// performance operation, and only intended for symbol tables that +// live across a large number of compiles. +// +void TSymbolTableLevel::relateToOperator(const char *name, TOperator op) { - TString mangledName("struct-"); - mangledName += *mName; - for (size_t i = 0; i < mFields->size(); ++i) { - mangledName += '-'; - mangledName += (*mFields)[i]->type()->getMangledName(); + for (tLevel::iterator it = level.begin(); it != level.end(); ++it) + { + if ((*it).second->isFunction()) + { + TFunction *function = static_cast((*it).second); + if (function->getName() == name) + function->relateToOperator(op); + } } - return mangledName; } -size_t TStructure::calculateObjectSize() const +// +// Change all function entries in the table with the non-mangled name +// to be related to the provided built-in extension. This is a low +// performance operation, and only intended for symbol tables that +// live across a large number of compiles. +// +void TSymbolTableLevel::relateToExtension(const char *name, const TString &ext) { - size_t size = 0; - for (size_t i = 0; i < mFields->size(); ++i) { - size_t fieldSize = (*mFields)[i]->type()->getObjectSize(); - if (fieldSize > INT_MAX - size) - size = INT_MAX; - else - size += fieldSize; + for (tLevel::iterator it = level.begin(); it != level.end(); ++it) + { + TSymbol *symbol = it->second; + if (symbol->getName() == name) + symbol->relateToExtension(ext); } - return size; } -int TStructure::calculateDeepestNesting() const +TSymbol::TSymbol(const TSymbol ©Of) { - int maxNesting = 0; - for (size_t i = 0; i < mFields->size(); ++i) { - maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting()); - } - return 1 + maxNesting; + name = NewPoolTString(copyOf.name->c_str()); + uniqueId = copyOf.uniqueId; } -// -// Dump functions. -// - -void TVariable::dump(TInfoSink& infoSink) const +TSymbol *TSymbolTable::find(const TString &name, int shaderVersion, bool *builtIn, bool *sameScope) { - infoSink.debug << getName().c_str() << ": " << type.getQualifierString() << " " << type.getPrecisionString() << " " << type.getBasicString(); - if (type.isArray()) { - infoSink.debug << "[0]"; + int level = currentLevel(); + TSymbol *symbol; + + do + { + if (level == ESSL3_BUILTINS && shaderVersion != 300) + level--; + if (level == ESSL1_BUILTINS && shaderVersion != 100) + level--; + + symbol = table[level]->find(name); } - infoSink.debug << "\n"; -} + while (symbol == 0 && --level >= 0); -void TFunction::dump(TInfoSink &infoSink) const -{ - infoSink.debug << getName().c_str() << ": " << returnType.getBasicString() << " " << getMangledName().c_str() << "\n"; -} + if (builtIn) + *builtIn = (level <= LAST_BUILTIN_LEVEL); + if (sameScope) + *sameScope = (level == currentLevel()); -void TSymbolTableLevel::dump(TInfoSink &infoSink) const -{ - tLevel::const_iterator it; - for (it = level.begin(); it != level.end(); ++it) - (*it).second->dump(infoSink); + return symbol; } -void TSymbolTable::dump(TInfoSink &infoSink) const +TSymbol *TSymbolTable::findBuiltIn(const TString &name, int shaderVersion) { - for (int level = currentLevel(); level >= 0; --level) { - infoSink.debug << "LEVEL " << level << "\n"; - table[level]->dump(infoSink); + for (int level = LAST_BUILTIN_LEVEL; level >= 0; level--) + { + if (level == ESSL3_BUILTINS && shaderVersion != 300) + level--; + if (level == ESSL1_BUILTINS && shaderVersion != 100) + level--; + + TSymbol *symbol = table[level]->find(name); + + if (symbol) + return symbol; } -} -// -// Functions have buried pointers to delete. -// -TFunction::~TFunction() -{ - for (TParamList::iterator i = parameters.begin(); i != parameters.end(); ++i) - delete (*i).type; + return 0; } -// -// Symbol table levels are a map of pointers to symbols that have to be deleted. -// -TSymbolTableLevel::~TSymbolTableLevel() +TSymbolTable::~TSymbolTable() { - for (tLevel::iterator it = level.begin(); it != level.end(); ++it) - delete (*it).second; + while (table.size() > 0) + pop(); } -// -// Change all function entries in the table with the non-mangled name -// to be related to the provided built-in operation. This is a low -// performance operation, and only intended for symbol tables that -// live across a large number of compiles. -// -void TSymbolTableLevel::relateToOperator(const char* name, TOperator op) +void TSymbolTable::insertBuiltIn( + ESymbolLevel level, TType *rvalue, const char *name, + TType *ptype1, TType *ptype2, TType *ptype3, TType *ptype4, TType *ptype5) { - tLevel::iterator it; - for (it = level.begin(); it != level.end(); ++it) { - if ((*it).second->isFunction()) { - TFunction* function = static_cast((*it).second); - if (function->getName() == name) - function->relateToOperator(op); - } + if (ptype1->getBasicType() == EbtGSampler2D) + { + bool gvec4 = (rvalue->getBasicType() == EbtGVec4); + insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, + new TType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, + new TType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, + new TType(EbtUSampler2D), ptype2, ptype3, ptype4, ptype5); + return; + } + if (ptype1->getBasicType() == EbtGSampler3D) + { + bool gvec4 = (rvalue->getBasicType() == EbtGVec4); + insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, + new TType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, + new TType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, + new TType(EbtUSampler3D), ptype2, ptype3, ptype4, ptype5); + return; + } + if (ptype1->getBasicType() == EbtGSamplerCube) + { + bool gvec4 = (rvalue->getBasicType() == EbtGVec4); + insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, + new TType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, + new TType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, + new TType(EbtUSamplerCube), ptype2, ptype3, ptype4, ptype5); + return; + } + if (ptype1->getBasicType() == EbtGSampler2DArray) + { + bool gvec4 = (rvalue->getBasicType() == EbtGVec4); + insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, + new TType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, + new TType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5); + insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, + new TType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5); + return; } -} -// -// Change all function entries in the table with the non-mangled name -// to be related to the provided built-in extension. This is a low -// performance operation, and only intended for symbol tables that -// live across a large number of compiles. -// -void TSymbolTableLevel::relateToExtension(const char* name, const TString& ext) -{ - for (tLevel::iterator it = level.begin(); it != level.end(); ++it) { - TSymbol* symbol = it->second; - if (symbol->getName() == name) - symbol->relateToExtension(ext); + TFunction *function = new TFunction(NewPoolTString(name), *rvalue); + + TType *types[] = {ptype1, ptype2, ptype3, ptype4, ptype5}; + for (size_t ii = 0; ii < sizeof(types) / sizeof(types[0]); ++ii) + { + if (types[ii]) + { + TParameter param = {NULL, types[ii]}; + function->addParameter(param); + } } + + insert(level, function); } -TSymbolTable::~TSymbolTable() +TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) { - for (size_t i = 0; i < table.size(); ++i) - delete table[i]; - for (size_t i = 0; i < precisionStack.size(); ++i) - delete precisionStack[i]; + if (!SupportsPrecision(type)) + return EbpUndefined; + + // unsigned integers use the same precision as signed + TBasicType baseType = (type == EbtUInt) ? EbtInt : type; + + int level = static_cast(precisionStack.size()) - 1; + assert(level >= 0); // Just to be safe. Should not happen. + // If we dont find anything we return this. Should we error check this? + TPrecision prec = EbpUndefined; + while (level >= 0) + { + PrecisionStackLevel::iterator it = precisionStack[level]->find(baseType); + if (it != precisionStack[level]->end()) + { + prec = (*it).second; + break; + } + level--; + } + return prec; } diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h index 6c7211f2a9..d3ddf19e34 100644 --- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h +++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2013 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. // @@ -36,34 +36,62 @@ #include "compiler/translator/InfoSink.h" #include "compiler/translator/intermediate.h" -// -// Symbol base class. (Can build functions or variables out of these...) -// -class TSymbol { -public: +// Symbol base class. (Can build functions or variables out of these...) +class TSymbol +{ + public: POOL_ALLOCATOR_NEW_DELETE(); - TSymbol(const TString* n) : uniqueId(0), name(n) { } - virtual ~TSymbol() { /* don't delete name, it's from the pool */ } - - const TString& getName() const { return *name; } - virtual const TString& getMangledName() const { return getName(); } - virtual bool isFunction() const { return false; } - virtual bool isVariable() const { return false; } - void setUniqueId(int id) { uniqueId = id; } - int getUniqueId() const { return uniqueId; } - virtual void dump(TInfoSink &infoSink) const = 0; - void relateToExtension(const TString& ext) { extension = ext; } - const TString& getExtension() const { return extension; } - -private: + TSymbol(const TString *n) + : uniqueId(0), + name(n) + { + } + virtual ~TSymbol() + { + // don't delete name, it's from the pool + } + + const TString &getName() const + { + return *name; + } + virtual const TString &getMangledName() const + { + return getName(); + } + virtual bool isFunction() const + { + return false; + } + virtual bool isVariable() const + { + return false; + } + void setUniqueId(int id) + { + uniqueId = id; + } + int getUniqueId() const + { + return uniqueId; + } + void relateToExtension(const TString &ext) + { + extension = ext; + } + const TString &getExtension() const + { + return extension; + } + + private: DISALLOW_COPY_AND_ASSIGN(TSymbol); - int uniqueId; // For real comparing during code generation + int uniqueId; // For real comparing during code generation const TString *name; TString extension; }; -// // Variable class, meaning a symbol that's not a function. // // There could be a separate class heirarchy for Constant variables; @@ -72,20 +100,41 @@ private: // seem worth having separate classes, and "getConst" can't simply return // different values for different types polymorphically, so this is // just simple and pragmatic. -// -class TVariable : public TSymbol { -public: - TVariable(const TString *name, const TType& t, bool uT = false ) : TSymbol(name), type(t), userType(uT), unionArray(0) { } - virtual ~TVariable() { } - virtual bool isVariable() const { return true; } - TType& getType() { return type; } - const TType& getType() const { return type; } - bool isUserType() const { return userType; } - void setQualifier(TQualifier qualifier) { type.setQualifier(qualifier); } - - virtual void dump(TInfoSink &infoSink) const; - - ConstantUnion* getConstPointer() +class TVariable : public TSymbol +{ + public: + TVariable(const TString *name, const TType &t, bool uT = false) + : TSymbol(name), + type(t), + userType(uT), + unionArray(0) + { + } + virtual ~TVariable() + { + } + virtual bool isVariable() const + { + return true; + } + TType &getType() + { + return type; + } + const TType &getType() const + { + return type; + } + bool isUserType() const + { + return userType; + } + void setQualifier(TQualifier qualifier) + { + type.setQualifier(qualifier); + } + + ConstantUnion *getConstPointer() { if (!unionArray) unionArray = new ConstantUnion[type.getObjectSize()]; @@ -93,9 +142,12 @@ public: return unionArray; } - ConstantUnion* getConstPointer() const { return unionArray; } + ConstantUnion *getConstPointer() const + { + return unionArray; + } - void shareConstPointer( ConstantUnion *constArray) + void shareConstPointer(ConstantUnion *constArray) { if (unionArray == constArray) return; @@ -104,71 +156,101 @@ public: unionArray = constArray; } -private: + private: DISALLOW_COPY_AND_ASSIGN(TVariable); TType type; bool userType; - // we are assuming that Pool Allocator will free the memory allocated to unionArray - // when this object is destroyed + // we are assuming that Pool Allocator will free the memory + // allocated to unionArray when this object is destroyed. ConstantUnion *unionArray; }; -// // The function sub-class of symbols and the parser will need to // share this definition of a function parameter. -// -struct TParameter { +struct TParameter +{ TString *name; - TType* type; + TType *type; }; -// // The function sub-class of a symbol. -// -class TFunction : public TSymbol { -public: - TFunction(TOperator o) : - TSymbol(0), - returnType(TType(EbtVoid, EbpUndefined)), - op(o), - defined(false) { } - TFunction(const TString *name, TType& retType, TOperator tOp = EOpNull) : - TSymbol(name), - returnType(retType), - mangledName(TFunction::mangleName(*name)), - op(tOp), - defined(false) { } +class TFunction : public TSymbol +{ + public: + TFunction(TOperator o) + : TSymbol(0), + returnType(TType(EbtVoid, EbpUndefined)), + op(o), + defined(false) + { + } + TFunction(const TString *name, const TType &retType, TOperator tOp = EOpNull) + : TSymbol(name), + returnType(retType), + mangledName(TFunction::mangleName(*name)), + op(tOp), + defined(false) + { + } virtual ~TFunction(); - virtual bool isFunction() const { return true; } + virtual bool isFunction() const + { + return true; + } - static TString mangleName(const TString& name) { return name + '('; } - static TString unmangleName(const TString& mangledName) + static TString mangleName(const TString &name) + { + return name + '('; + } + static TString unmangleName(const TString &mangledName) { return TString(mangledName.c_str(), mangledName.find_first_of('(')); } - void addParameter(TParameter& p) + void addParameter(TParameter &p) { parameters.push_back(p); mangledName = mangledName + p.type->getMangledName(); } - const TString& getMangledName() const { return mangledName; } - const TType& getReturnType() const { return returnType; } - - void relateToOperator(TOperator o) { op = o; } - TOperator getBuiltInOp() const { return op; } + const TString &getMangledName() const + { + return mangledName; + } + const TType &getReturnType() const + { + return returnType; + } - void setDefined() { defined = true; } - bool isDefined() { return defined; } + void relateToOperator(TOperator o) + { + op = o; + } + TOperator getBuiltInOp() const + { + return op; + } - size_t getParamCount() const { return parameters.size(); } - const TParameter& getParam(size_t i) const { return parameters[i]; } + void setDefined() + { + defined = true; + } + bool isDefined() + { + return defined; + } - virtual void dump(TInfoSink &infoSink) const; + size_t getParamCount() const + { + return parameters.size(); + } + const TParameter &getParam(size_t i) const + { + return parameters[i]; + } -private: + private: DISALLOW_COPY_AND_ASSIGN(TFunction); typedef TVector TParamList; @@ -179,79 +261,80 @@ private: bool defined; }; - -class TSymbolTableLevel { -public: - typedef TMap tLevel; - typedef tLevel::const_iterator const_iterator; - typedef const tLevel::value_type tLevelPair; - typedef std::pair tInsertResult; - - TSymbolTableLevel() { } - ~TSymbolTableLevel(); - - bool insert(const TString &name, TSymbol &symbol) +// Interface block name sub-symbol +class TInterfaceBlockName : public TSymbol +{ + public: + TInterfaceBlockName(const TString *name) + : TSymbol(name) { - // - // returning true means symbol was added to the table - // - tInsertResult result = level.insert(tLevelPair(name, &symbol)); - - return result.second; } - bool insert(TSymbol &symbol) + virtual ~TInterfaceBlockName() { - return insert(symbol.getMangledName(), symbol); } +}; - TSymbol* find(const TString& name) const - { - tLevel::const_iterator it = level.find(name); - if (it == level.end()) - return 0; - else - return (*it).second; - } +class TSymbolTableLevel +{ + public: + typedef TMap tLevel; + typedef tLevel::const_iterator const_iterator; + typedef const tLevel::value_type tLevelPair; + typedef std::pair tInsertResult; - const_iterator begin() const + TSymbolTableLevel() { - return level.begin(); } + ~TSymbolTableLevel(); - const_iterator end() const - { - return level.end(); - } + bool insert(TSymbol *symbol); - void relateToOperator(const char* name, TOperator op); - void relateToExtension(const char* name, const TString& ext); - void dump(TInfoSink &infoSink) const; + TSymbol *find(const TString &name) const; -protected: + void relateToOperator(const char *name, TOperator op); + void relateToExtension(const char *name, const TString &ext); + + protected: tLevel level; }; -class TSymbolTable { -public: - TSymbolTable() : uniqueId(0) +enum ESymbolLevel +{ + COMMON_BUILTINS = 0, + ESSL1_BUILTINS = 1, + ESSL3_BUILTINS = 2, + LAST_BUILTIN_LEVEL = ESSL3_BUILTINS, + GLOBAL_LEVEL = 3 +}; + +class TSymbolTable +{ + public: + TSymbolTable() { - // // The symbol table cannot be used until push() is called, but // the lack of an initial call to push() can be used to detect // that the symbol table has not been preloaded with built-ins. - // } + ~TSymbolTable(); - // // When the symbol table is initialized with the built-ins, there should // 'push' calls, so that built-ins are at level 0 and the shader // globals are at level 1. - // - bool isEmpty() { return table.size() == 0; } - bool atBuiltInLevel() { return table.size() == 1; } - bool atGlobalLevel() { return table.size() <= 2; } + bool isEmpty() + { + return table.empty(); + } + bool atBuiltInLevel() + { + return currentLevel() <= LAST_BUILTIN_LEVEL; + } + bool atGlobalLevel() + { + return currentLevel() <= GLOBAL_LEVEL; + } void push() { table.push_back(new TSymbolTableLevel); @@ -267,116 +350,80 @@ public: precisionStack.pop_back(); } - bool insert(TSymbol& symbol) + bool declare(TSymbol *symbol) { - symbol.setUniqueId(++uniqueId); - return table[currentLevel()]->insert(symbol); + return insert(currentLevel(), symbol); } - bool insertConstInt(const char *name, int value) + bool insert(ESymbolLevel level, TSymbol *symbol) { - TVariable *constant = new TVariable(NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1)); - constant->getConstPointer()->setIConst(value); - return insert(*constant); + return table[level]->insert(symbol); } - bool insertBuiltIn(TType *rvalue, const char *name, TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0) + bool insertConstInt(ESymbolLevel level, const char *name, int value) { - TFunction *function = new TFunction(NewPoolTString(name), *rvalue); - - TParameter param1 = {NULL, ptype1}; - function->addParameter(param1); - - if(ptype2) - { - TParameter param2 = {NULL, ptype2}; - function->addParameter(param2); - } - - if(ptype3) - { - TParameter param3 = {NULL, ptype3}; - function->addParameter(param3); - } - - return insert(*function); + TVariable *constant = new TVariable( + NewPoolTString(name), TType(EbtInt, EbpUndefined, EvqConst, 1)); + constant->getConstPointer()->setIConst(value); + return insert(level, constant); } - TSymbol* find(const TString& name, bool* builtIn = 0, bool *sameScope = 0) - { - int level = currentLevel(); - TSymbol* symbol; - do { - symbol = table[level]->find(name); - --level; - } while (symbol == 0 && level >= 0); - level++; - if (builtIn) - *builtIn = level == 0; - if (sameScope) - *sameScope = level == currentLevel(); - return symbol; - } + void insertBuiltIn(ESymbolLevel level, TType *rvalue, const char *name, + TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, + TType *ptype4 = 0, TType *ptype5 = 0); - TSymbol* findBuiltIn(const TString &name) + TSymbol *find(const TString &name, int shaderVersion, + bool *builtIn = NULL, bool *sameScope = NULL); + TSymbol *findBuiltIn(const TString &name, int shaderVersion); + + TSymbolTableLevel *getOuterLevel() { - return table[0]->find(name); - } - - TSymbolTableLevel* getOuterLevel() { - assert(table.size() >= 2); + assert(currentLevel() >= 1); return table[currentLevel() - 1]; } - void relateToOperator(const char* name, TOperator op) { - table[0]->relateToOperator(name, op); + void relateToOperator(ESymbolLevel level, const char *name, TOperator op) + { + table[level]->relateToOperator(name, op); } - void relateToExtension(const char* name, const TString& ext) { - table[0]->relateToExtension(name, ext); + void relateToExtension(ESymbolLevel level, const char *name, const TString &ext) + { + table[level]->relateToExtension(name, ext); } void dump(TInfoSink &infoSink) const; - bool setDefaultPrecision(const TPublicType& type, TPrecision prec) { - if (!supportsPrecision(type.type)) + bool setDefaultPrecision(const TPublicType &type, TPrecision prec) + { + if (!SupportsPrecision(type.type)) return false; - if (type.size != 1 || type.matrix || type.array) + if (type.isAggregate()) return false; // Not allowed to set for aggregate types int indexOfLastElement = static_cast(precisionStack.size()) - 1; - (*precisionStack[indexOfLastElement])[type.type] = prec; // Uses map operator [], overwrites the current value + // Uses map operator [], overwrites the current value + (*precisionStack[indexOfLastElement])[type.type] = prec; return true; } - // Searches down the precisionStack for a precision qualifier for the specified TBasicType - TPrecision getDefaultPrecision(TBasicType type) { - if (!supportsPrecision(type)) - return EbpUndefined; - int level = static_cast(precisionStack.size()) - 1; - assert(level >= 0); // Just to be safe. Should not happen. - PrecisionStackLevel::iterator it; - TPrecision prec = EbpUndefined; // If we dont find anything we return this. Should we error check this? - while (level >= 0) { - it = precisionStack[level]->find(type); - if (it != precisionStack[level]->end()) { - prec = (*it).second; - break; - } - level--; - } - return prec; - } + // Searches down the precisionStack for a precision qualifier + // for the specified TBasicType + TPrecision getDefaultPrecision(TBasicType type); -private: - int currentLevel() const { return static_cast(table.size()) - 1; } + static int nextUniqueId() + { + return ++uniqueIdCounter; + } - bool supportsPrecision(TBasicType type) { - // Only supports precision for int, float, and sampler types. - return type == EbtFloat || type == EbtInt || IsSampler(type); + private: + ESymbolLevel currentLevel() const + { + return static_cast(table.size() - 1); } - int uniqueId; // for unique identification in code generation - std::vector table; + std::vector table; typedef TMap PrecisionStackLevel; - std::vector precisionStack; + std::vector< PrecisionStackLevel *> precisionStack; + + static int uniqueIdCounter; }; #endif // _SYMBOL_TABLE_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp index 9262f7af8c..5b99fea948 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -7,9 +7,10 @@ #include "compiler/translator/TranslatorESSL.h" #include "compiler/translator/OutputESSL.h" +#include "angle_gl.h" -TranslatorESSL::TranslatorESSL(ShShaderType type, ShShaderSpec spec) - : TCompiler(type, spec) { +TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec) + : TCompiler(type, spec, SH_ESSL_OUTPUT) { } void TranslatorESSL::translate(TIntermNode* root) { @@ -20,13 +21,13 @@ void TranslatorESSL::translate(TIntermNode* root) { // Write emulated built-in functions if needed. getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition( - sink, getShaderType() == SH_FRAGMENT_SHADER); + sink, getShaderType() == GL_FRAGMENT_SHADER); // Write array bounds clamping emulation if needed. getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); // Write translated shader. - TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable()); + TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable(), getShaderVersion()); root->traverse(&outputESSL); } diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h index e18f3c25ec..55766822d1 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h @@ -7,11 +7,11 @@ #ifndef COMPILER_TRANSLATORESSL_H_ #define COMPILER_TRANSLATORESSL_H_ -#include "compiler/translator/ShHandle.h" +#include "compiler/translator/Compiler.h" class TranslatorESSL : public TCompiler { public: - TranslatorESSL(ShShaderType type, ShShaderSpec spec); + TranslatorESSL(sh::GLenum type, ShShaderSpec spec); protected: virtual void translate(TIntermNode* root); diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp index 6688d7f362..4b2aecab33 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -9,7 +9,7 @@ #include "compiler/translator/OutputGLSL.h" #include "compiler/translator/VersionGLSL.h" -static void writeVersion(ShShaderType type, TIntermNode* root, +static void writeVersion(sh::GLenum type, TIntermNode* root, TInfoSinkBase& sink) { TVersionGLSL versionGLSL(type); root->traverse(&versionGLSL); @@ -21,8 +21,8 @@ static void writeVersion(ShShaderType type, TIntermNode* root, } } -TranslatorGLSL::TranslatorGLSL(ShShaderType type, ShShaderSpec spec) - : TCompiler(type, spec) { +TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec) + : TCompiler(type, spec, SH_GLSL_OUTPUT) { } void TranslatorGLSL::translate(TIntermNode* root) { @@ -31,6 +31,9 @@ void TranslatorGLSL::translate(TIntermNode* root) { // Write GLSL version. writeVersion(getShaderType(), root, sink); + // Write extension behaviour as needed + writeExtensionBehavior(); + // Write emulated built-in functions if needed. getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition( sink, false); @@ -39,6 +42,23 @@ void TranslatorGLSL::translate(TIntermNode* root) { getArrayBoundsClamper().OutputClampingFunctionDefinition(sink); // Write translated shader. - TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable()); + TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable(), getShaderVersion()); root->traverse(&outputGLSL); } + +void TranslatorGLSL::writeExtensionBehavior() { + TInfoSinkBase& sink = getInfoSink().obj; + const TExtensionBehavior& extensionBehavior = getExtensionBehavior(); + for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin(); + iter != extensionBehavior.end(); ++iter) { + if (iter->second == EBhUndefined) + continue; + + // For GLSL output, we don't need to emit most extensions explicitly, + // but some we need to translate. + if (iter->first == "GL_EXT_shader_texture_lod") { + sink << "#extension GL_ARB_shader_texture_lod : " + << getBehaviorString(iter->second) << "\n"; + } + } +} diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h index 40bb3145e8..3c6c2e426a 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h @@ -7,14 +7,17 @@ #ifndef COMPILER_TRANSLATORGLSL_H_ #define COMPILER_TRANSLATORGLSL_H_ -#include "compiler/translator/ShHandle.h" +#include "compiler/translator/Compiler.h" class TranslatorGLSL : public TCompiler { public: - TranslatorGLSL(ShShaderType type, ShShaderSpec spec); + TranslatorGLSL(sh::GLenum type, ShShaderSpec spec); protected: virtual void translate(TIntermNode* root); + +private: + void writeExtensionBehavior(); }; #endif // COMPILER_TRANSLATORGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp index 3c1db011b6..52588e4626 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp @@ -9,16 +9,46 @@ #include "compiler/translator/InitializeParseContext.h" #include "compiler/translator/OutputHLSL.h" -TranslatorHLSL::TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output) - : TCompiler(type, spec), mOutputType(output) +TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) + : TCompiler(type, spec, output) { } void TranslatorHLSL::translate(TIntermNode *root) { TParseContext& parseContext = *GetGlobalParseContext(); - sh::OutputHLSL outputHLSL(parseContext, getResources(), mOutputType); + sh::OutputHLSL outputHLSL(parseContext, getResources(), getOutputType()); outputHLSL.output(); - mActiveUniforms = outputHLSL.getUniforms(); + + attributes = outputHLSL.getAttributes(); + outputVariables = outputHLSL.getOutputVariables(); + uniforms = outputHLSL.getUniforms(); + varyings = outputHLSL.getVaryings(); + interfaceBlocks = outputHLSL.getInterfaceBlocks(); + + mInterfaceBlockRegisterMap = outputHLSL.getInterfaceBlockRegisterMap(); + mUniformRegisterMap = outputHLSL.getUniformRegisterMap(); +} + +bool TranslatorHLSL::hasInterfaceBlock(const std::string &interfaceBlockName) const +{ + return (mInterfaceBlockRegisterMap.count(interfaceBlockName) > 0); +} + +unsigned int TranslatorHLSL::getInterfaceBlockRegister(const std::string &interfaceBlockName) const +{ + ASSERT(hasInterfaceBlock(interfaceBlockName)); + return mInterfaceBlockRegisterMap.find(interfaceBlockName)->second; +} + +bool TranslatorHLSL::hasUniform(const std::string &uniformName) const +{ + return (mUniformRegisterMap.count(uniformName) > 0); +} + +unsigned int TranslatorHLSL::getUniformRegister(const std::string &uniformName) const +{ + ASSERT(hasUniform(uniformName)); + return mUniformRegisterMap.find(uniformName)->second; } diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h index 6204b30cc2..598c8a7b30 100644 --- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h @@ -7,21 +7,26 @@ #ifndef COMPILER_TRANSLATORHLSL_H_ #define COMPILER_TRANSLATORHLSL_H_ -#include "compiler/translator/ShHandle.h" -#include "compiler/translator/Uniform.h" - -class TranslatorHLSL : public TCompiler { -public: - TranslatorHLSL(ShShaderType type, ShShaderSpec spec, ShShaderOutput output); +#include "compiler/translator/Compiler.h" +#include "common/shadervars.h" +class TranslatorHLSL : public TCompiler +{ + public: + TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output); virtual TranslatorHLSL *getAsTranslatorHLSL() { return this; } - const sh::ActiveUniforms &getUniforms() { return mActiveUniforms; } -protected: + bool hasInterfaceBlock(const std::string &interfaceBlockName) const; + unsigned int getInterfaceBlockRegister(const std::string &interfaceBlockName) const; + + bool hasUniform(const std::string &uniformName) const; + unsigned int getUniformRegister(const std::string &uniformName) const; + + protected: virtual void translate(TIntermNode* root); - sh::ActiveUniforms mActiveUniforms; - ShShaderOutput mOutputType; + std::map mInterfaceBlockRegisterMap; + std::map mUniformRegisterMap; }; #endif // COMPILER_TRANSLATORHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/Types.cpp b/src/3rdparty/angle/src/compiler/translator/Types.cpp new file mode 100644 index 0000000000..bafad0d64f --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/Types.cpp @@ -0,0 +1,202 @@ +// +// 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. +// + +#if defined(_MSC_VER) +#pragma warning(disable: 4718) +#endif + +#include "compiler/translator/Types.h" + +#include +#include + +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), + interfaceBlock(0), structure(0) +{ + if (p.userDef) + structure = p.userDef->getStruct(); +} + +bool TStructure::equals(const TStructure &other) const +{ + return (uniqueId() == other.uniqueId()); +} + +// +// Recursively generate mangled names. +// +TString TType::buildMangledName() const +{ + TString mangledName; + if (isMatrix()) + mangledName += 'm'; + else if (isVector()) + mangledName += 'v'; + + switch (type) + { + case EbtFloat: + mangledName += 'f'; + break; + case EbtInt: + mangledName += 'i'; + break; + case EbtUInt: + mangledName += 'u'; + break; + case EbtBool: + mangledName += 'b'; + break; + case EbtSampler2D: + mangledName += "s2"; + break; + case EbtSampler3D: + mangledName += "s3"; + break; + case EbtSamplerCube: + mangledName += "sC"; + break; + case EbtSampler2DArray: + mangledName += "s2a"; + break; + case EbtSamplerExternalOES: + mangledName += "sext"; + break; + case EbtSampler2DRect: + mangledName += "s2r"; + break; + case EbtISampler2D: + mangledName += "is2"; + break; + case EbtISampler3D: + mangledName += "is3"; + break; + case EbtISamplerCube: + mangledName += "isC"; + break; + case EbtISampler2DArray: + mangledName += "is2a"; + break; + case EbtUSampler2D: + mangledName += "us2"; + break; + case EbtUSampler3D: + mangledName += "us3"; + break; + case EbtUSamplerCube: + mangledName += "usC"; + break; + case EbtUSampler2DArray: + mangledName += "us2a"; + break; + case EbtSampler2DShadow: + mangledName += "s2s"; + break; + case EbtSamplerCubeShadow: + mangledName += "sCs"; + break; + case EbtSampler2DArrayShadow: + mangledName += "s2as"; + break; + case EbtStruct: + mangledName += structure->mangledName(); + break; + case EbtInterfaceBlock: + mangledName += interfaceBlock->mangledName(); + break; + default: + UNREACHABLE(); + } + + if (isMatrix()) + { + mangledName += static_cast('0' + getCols()); + mangledName += static_cast('x'); + mangledName += static_cast('0' + getRows()); + } + else + { + mangledName += static_cast('0' + getNominalSize()); + } + + if (isArray()) + { + char buf[20]; + snprintf(buf, sizeof(buf), "%d", arraySize); + mangledName += '['; + mangledName += buf; + mangledName += ']'; + } + return mangledName; +} + +size_t TType::getObjectSize() const +{ + size_t totalSize; + + if (getBasicType() == EbtStruct) + totalSize = structure->objectSize(); + else + totalSize = primarySize * secondarySize; + + if (isArray()) + { + size_t arraySize = getArraySize(); + if (arraySize > INT_MAX / totalSize) + totalSize = INT_MAX; + else + totalSize *= arraySize; + } + + return totalSize; +} + +bool TStructure::containsArrays() const +{ + for (size_t i = 0; i < mFields->size(); ++i) + { + const TType *fieldType = (*mFields)[i]->type(); + if (fieldType->isArray() || fieldType->isStructureContainingArrays()) + return true; + } + return false; +} + +TString TFieldListCollection::buildMangledName() const +{ + TString mangledName(mangledNamePrefix()); + mangledName += *mName; + for (size_t i = 0; i < mFields->size(); ++i) + { + mangledName += '-'; + mangledName += (*mFields)[i]->type()->getMangledName(); + } + return mangledName; +} + +size_t TFieldListCollection::calculateObjectSize() const +{ + size_t size = 0; + for (size_t i = 0; i < mFields->size(); ++i) + { + size_t fieldSize = (*mFields)[i]->type()->getObjectSize(); + if (fieldSize > INT_MAX - size) + size = INT_MAX; + else + size += fieldSize; + } + return size; +} + +int TStructure::calculateDeepestNesting() const +{ + int maxNesting = 0; + for (size_t i = 0; i < mFields->size(); ++i) + maxNesting = std::max(maxNesting, (*mFields)[i]->type()->getDeepestStructNesting()); + return 1 + maxNesting; +} diff --git a/src/3rdparty/angle/src/compiler/translator/Types.h b/src/3rdparty/angle/src/compiler/translator/Types.h index 119f4f29e5..bc50a4dc64 100644 --- a/src/3rdparty/angle/src/compiler/translator/Types.h +++ b/src/3rdparty/angle/src/compiler/translator/Types.h @@ -15,76 +15,191 @@ struct TPublicType; class TType; +class TSymbol; class TField { -public: + public: POOL_ALLOCATOR_NEW_DELETE(); - TField(TType* type, TString* name) : mType(type), mName(name) {} + TField(TType *type, TString *name, const TSourceLoc &line) + : mType(type), + mName(name), + mLine(line) + { + } // TODO(alokp): We should only return const type. // Fix it by tweaking grammar. - TType* type() { return mType; } - const TType* type() const { return mType; } + TType *type() + { + return mType; + } + const TType *type() const + { + return mType; + } - const TString& name() const { return *mName; } + const TString &name() const + { + return *mName; + } + const TSourceLoc &line() const + { + return mLine; + } -private: + private: DISALLOW_COPY_AND_ASSIGN(TField); - TType* mType; - TString* mName; + TType *mType; + TString *mName; + TSourceLoc mLine; }; -typedef TVector TFieldList; -inline TFieldList* NewPoolTFieldList() +typedef TVector TFieldList; +inline TFieldList *NewPoolTFieldList() { - void* memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList)); + void *memory = GetGlobalPoolAllocator()->allocate(sizeof(TFieldList)); return new(memory) TFieldList; } -class TStructure +class TFieldListCollection { -public: - POOL_ALLOCATOR_NEW_DELETE(); - TStructure(TString* name, TFieldList* fields) - : mName(name), - mFields(fields), - mObjectSize(0), - mDeepestNesting(0) { + public: + const TString &name() const + { + return *mName; + } + const TFieldList &fields() const + { + return *mFields; } - const TString& name() const { return *mName; } - const TFieldList& fields() const { return *mFields; } - - const TString& mangledName() const { + const TString &mangledName() const + { if (mMangledName.empty()) mMangledName = buildMangledName(); return mMangledName; } - size_t objectSize() const { + size_t objectSize() const + { if (mObjectSize == 0) mObjectSize = calculateObjectSize(); return mObjectSize; }; - int deepestNesting() const { + + protected: + TFieldListCollection(const TString *name, TFieldList *fields) + : mName(name), + mFields(fields), + mObjectSize(0) + { + } + TString buildMangledName() const; + size_t calculateObjectSize() const; + virtual TString mangledNamePrefix() const = 0; + + const TString *mName; + TFieldList *mFields; + + mutable TString mMangledName; + mutable size_t mObjectSize; +}; + +// May also represent interface blocks +class TStructure : public TFieldListCollection +{ + public: + POOL_ALLOCATOR_NEW_DELETE(); + TStructure(const TString *name, TFieldList *fields) + : TFieldListCollection(name, fields), + mDeepestNesting(0), + mUniqueId(0) + { + } + + int deepestNesting() const + { if (mDeepestNesting == 0) mDeepestNesting = calculateDeepestNesting(); return mDeepestNesting; } bool containsArrays() const; -private: + bool equals(const TStructure &other) const; + + void setUniqueId(int uniqueId) + { + mUniqueId = uniqueId; + } + + int uniqueId() const + { + ASSERT(mUniqueId != 0); + return mUniqueId; + } + + private: DISALLOW_COPY_AND_ASSIGN(TStructure); - TString buildMangledName() const; - size_t calculateObjectSize() const; + virtual TString mangledNamePrefix() const + { + return "struct-"; + } int calculateDeepestNesting() const; - TString* mName; - TFieldList* mFields; - - mutable TString mMangledName; - mutable size_t mObjectSize; mutable int mDeepestNesting; + int mUniqueId; +}; + +class TInterfaceBlock : public TFieldListCollection +{ + public: + POOL_ALLOCATOR_NEW_DELETE(); + TInterfaceBlock(const TString *name, TFieldList *fields, const TString *instanceName, + int arraySize, const TLayoutQualifier &layoutQualifier) + : TFieldListCollection(name, fields), + mInstanceName(instanceName), + mArraySize(arraySize), + mBlockStorage(layoutQualifier.blockStorage), + mMatrixPacking(layoutQualifier.matrixPacking) + { + } + + const TString &instanceName() const + { + return *mInstanceName; + } + bool hasInstanceName() const + { + return mInstanceName != NULL; + } + bool isArray() const + { + return mArraySize > 0; + } + int arraySize() const + { + return mArraySize; + } + TLayoutBlockStorage blockStorage() const + { + return mBlockStorage; + } + TLayoutMatrixPacking matrixPacking() const + { + return mMatrixPacking; + } + + private: + DISALLOW_COPY_AND_ASSIGN(TInterfaceBlock); + virtual TString mangledNamePrefix() const + { + return "iblock-"; + } + + const TString *mInstanceName; // for interface block instance names + int mArraySize; // 0 if not an array + TLayoutBlockStorage mBlockStorage; + TLayoutMatrixPacking mMatrixPacking; }; // @@ -92,123 +207,228 @@ private: // class TType { -public: + public: POOL_ALLOCATOR_NEW_DELETE(); - TType() {} - TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, unsigned char s = 1, bool m = false, bool a = false) : - type(t), precision(p), qualifier(q), size(s), matrix(m), array(a), arraySize(0), structure(0) + TType() + { + } + TType(TBasicType t, unsigned char ps = 1, unsigned char ss = 1) + : type(t), precision(EbpUndefined), qualifier(EvqGlobal), + layoutQualifier(TLayoutQualifier::create()), + primarySize(ps), secondarySize(ss), array(false), arraySize(0), + interfaceBlock(0), structure(0) + { + } + TType(TBasicType t, TPrecision p, TQualifier q = EvqTemporary, + unsigned char ps = 1, unsigned char ss = 1, bool a = false) + : type(t), precision(p), qualifier(q), + layoutQualifier(TLayoutQualifier::create()), + primarySize(ps), secondarySize(ss), array(a), arraySize(0), + interfaceBlock(0), structure(0) { } explicit TType(const TPublicType &p); - TType(TStructure* userDef, TPrecision p = EbpUndefined) : - type(EbtStruct), precision(p), qualifier(EvqTemporary), size(1), matrix(false), array(false), arraySize(0), structure(userDef) + TType(TStructure *userDef, TPrecision p = EbpUndefined) + : type(EbtStruct), precision(p), qualifier(EvqTemporary), + layoutQualifier(TLayoutQualifier::create()), + primarySize(1), secondarySize(1), array(false), arraySize(0), + interfaceBlock(0), structure(userDef) + { + } + TType(TInterfaceBlock *interfaceBlockIn, TQualifier qualifierIn, + TLayoutQualifier layoutQualifierIn, int arraySizeIn) + : type(EbtInterfaceBlock), precision(EbpUndefined), qualifier(qualifierIn), + layoutQualifier(layoutQualifierIn), + primarySize(1), secondarySize(1), array(arraySizeIn > 0), arraySize(arraySizeIn), + interfaceBlock(interfaceBlockIn), structure(0) { } - TBasicType getBasicType() const { return type; } - void setBasicType(TBasicType t) { type = t; } + TBasicType getBasicType() const + { + return type; + } + void setBasicType(TBasicType t) + { + type = t; + } - TPrecision getPrecision() const { return precision; } - void setPrecision(TPrecision p) { precision = p; } + TPrecision getPrecision() const + { + return precision; + } + void setPrecision(TPrecision p) + { + precision = p; + } - TQualifier getQualifier() const { return qualifier; } - void setQualifier(TQualifier q) { qualifier = q; } + TQualifier getQualifier() const + { + return qualifier; + } + void setQualifier(TQualifier q) + { + qualifier = q; + } - // One-dimensional size of single instance type - int getNominalSize() const { return size; } - void setNominalSize(unsigned char s) { size = s; } - // Full size of single instance of type - size_t getObjectSize() const; + TLayoutQualifier getLayoutQualifier() const + { + return layoutQualifier; + } + void setLayoutQualifier(TLayoutQualifier lq) + { + layoutQualifier = lq; + } - int elementRegisterCount() const + int getNominalSize() const { - if (structure) - { - const TFieldList &fields = getStruct()->fields(); - int registerCount = 0; + return primarySize; + } + int getSecondarySize() const + { + return secondarySize; + } + int getCols() const + { + ASSERT(isMatrix()); + return primarySize; + } + int getRows() const + { + ASSERT(isMatrix()); + return secondarySize; + } + void setPrimarySize(unsigned char ps) + { + primarySize = ps; + } + void setSecondarySize(unsigned char ss) + { + secondarySize = ss; + } - for (size_t i = 0; i < fields.size(); i++) - { - registerCount += fields[i]->type()->totalRegisterCount(); - } + // Full size of single instance of type + size_t getObjectSize() const; - return registerCount; - } - else if (isMatrix()) - { - return getNominalSize(); - } - else - { - return 1; - } + bool isMatrix() const + { + return primarySize > 1 && secondarySize > 1; } - - int totalRegisterCount() const + bool isArray() const { - if (array) - { - return arraySize * elementRegisterCount(); - } - else - { - return elementRegisterCount(); - } + return array ? true : false; + } + int getArraySize() const + { + return arraySize; + } + void setArraySize(int s) + { + array = true; + arraySize = s; + } + void clearArrayness() + { + array = false; + arraySize = 0; } - bool isMatrix() const { return matrix ? true : false; } - void setMatrix(bool m) { matrix = m; } - - bool isArray() const { return array ? true : false; } - int getArraySize() const { return arraySize; } - void setArraySize(int s) { array = true; arraySize = s; } - void clearArrayness() { array = false; arraySize = 0; } + TInterfaceBlock *getInterfaceBlock() const + { + return interfaceBlock; + } + void setInterfaceBlock(TInterfaceBlock *interfaceBlockIn) + { + interfaceBlock = interfaceBlockIn; + } + bool isInterfaceBlock() const + { + return type == EbtInterfaceBlock; + } - bool isVector() const { return size > 1 && !matrix; } - bool isScalar() const { return size == 1 && !matrix && !structure; } + bool isVector() const + { + return primarySize > 1 && secondarySize == 1; + } + bool isScalar() const + { + return primarySize == 1 && secondarySize == 1 && !structure; + } + bool isScalarInt() const + { + return isScalar() && (type == EbtInt || type == EbtUInt); + } - TStructure* getStruct() const { return structure; } - void setStruct(TStructure* s) { structure = s; } + TStructure *getStruct() const + { + return structure; + } + void setStruct(TStructure *s) + { + structure = s; + } - const TString& getMangledName() const { - if (mangled.empty()) { + const TString &getMangledName() + { + if (mangled.empty()) + { mangled = buildMangledName(); mangled += ';'; } + return mangled; } - bool sameElementType(const TType& right) const { - return type == right.type && - size == right.size && - matrix == right.matrix && - structure == right.structure; + bool sameElementType(const TType &right) const + { + return type == right.type && + primarySize == right.primarySize && + secondarySize == right.secondarySize && + structure == right.structure; } - bool operator==(const TType& right) const { - return type == right.type && - size == right.size && - matrix == right.matrix && - array == right.array && (!array || arraySize == right.arraySize) && - structure == right.structure; + bool operator==(const TType &right) const + { + return type == right.type && + primarySize == right.primarySize && + secondarySize == right.secondarySize && + array == right.array && (!array || arraySize == right.arraySize) && + structure == right.structure; // don't check the qualifier, it's not ever what's being sought after } - bool operator!=(const TType& right) const { + bool operator!=(const TType &right) const + { return !operator==(right); } - bool operator<(const TType& right) const { - if (type != right.type) return type < right.type; - if (size != right.size) return size < right.size; - if (matrix != right.matrix) return matrix < right.matrix; - if (array != right.array) return array < right.array; - if (arraySize != right.arraySize) return arraySize < right.arraySize; - if (structure != right.structure) return structure < right.structure; + bool operator<(const TType &right) const + { + if (type != right.type) + return type < right.type; + if (primarySize != right.primarySize) + return primarySize < right.primarySize; + if (secondarySize != right.secondarySize) + return secondarySize < right.secondarySize; + if (array != right.array) + return array < right.array; + if (arraySize != right.arraySize) + return arraySize < right.arraySize; + if (structure != right.structure) + return structure < right.structure; return false; } - const char* getBasicString() const { return ::getBasicString(type); } - const char* getPrecisionString() const { return ::getPrecisionString(precision); } - const char* getQualifierString() const { return ::getQualifierString(qualifier); } + const char *getBasicString() const + { + return ::getBasicString(type); + } + const char *getPrecisionString() const + { + return ::getPrecisionString(precision); + } + const char *getQualifierString() const + { + return ::getQualifierString(qualifier); + } TString getCompleteString() const; // If this type is a struct, returns the deepest struct nesting of @@ -223,26 +443,35 @@ public: // For type "nesting2", this method would return 2 -- the number // of structures through which indirection must occur to reach the // deepest field (nesting2.field1.position). - int getDeepestStructNesting() const { + int getDeepestStructNesting() const + { return structure ? structure->deepestNesting() : 0; } - bool isStructureContainingArrays() const { + bool isStructureContainingArrays() const + { return structure ? structure->containsArrays() : false; } -private: + protected: TString buildMangledName() const; + size_t getStructSize() const; + void computeDeepestStructNesting(); TBasicType type; TPrecision precision; TQualifier qualifier; - unsigned char size; - bool matrix; + TLayoutQualifier layoutQualifier; + unsigned char primarySize; // size of vector or cols matrix + unsigned char secondarySize; // rows of a matrix bool array; int arraySize; - TStructure* structure; // 0 unless this is a struct + // 0 unless this is an interface block, or interface block member variable + TInterfaceBlock *interfaceBlock; + + // 0 unless this is a struct + TStructure *structure; mutable TString mangled; }; @@ -259,32 +488,40 @@ private: struct TPublicType { TBasicType type; + TLayoutQualifier layoutQualifier; TQualifier qualifier; TPrecision precision; - unsigned char size; // size of vector or matrix, not size of array - bool matrix; + unsigned char primarySize; // size of vector or cols of matrix + unsigned char secondarySize; // rows of matrix bool array; int arraySize; - TType* userDef; + TType *userDef; TSourceLoc line; - void setBasic(TBasicType bt, TQualifier q, const TSourceLoc& ln) + void setBasic(TBasicType bt, TQualifier q, const TSourceLoc &ln) { type = bt; + layoutQualifier = TLayoutQualifier::create(); qualifier = q; precision = EbpUndefined; - size = 1; - matrix = false; + primarySize = 1; + secondarySize = 1; array = false; arraySize = 0; userDef = 0; line = ln; } - void setAggregate(unsigned char s, bool m = false) + void setAggregate(unsigned char size) + { + primarySize = size; + } + + void setMatrix(unsigned char c, unsigned char r) { - size = s; - matrix = m; + ASSERT(c > 1 && r > 1 && c <= 4 && r <= 4); + primarySize = c; + secondarySize = r; } void setArray(bool a, int s = 0) @@ -302,6 +539,38 @@ struct TPublicType return userDef->isStructureContainingArrays(); } + + bool isMatrix() const + { + return primarySize > 1 && secondarySize > 1; + } + + bool isVector() const + { + return primarySize > 1 && secondarySize == 1; + } + + int getCols() const + { + ASSERT(isMatrix()); + return primarySize; + } + + int getRows() const + { + ASSERT(isMatrix()); + return secondarySize; + } + + int getNominalSize() const + { + return primarySize; + } + + bool isAggregate() const + { + return array || isMatrix() || isVector(); + } }; #endif // _TYPES_INCLUDED_ diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp index b7826119ae..65f50c4cc3 100644 --- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp +++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp @@ -12,6 +12,7 @@ #include "compiler/translator/InfoSink.h" #include "compiler/translator/OutputHLSL.h" +#include "compiler/translator/UtilsHLSL.h" namespace sh { @@ -117,7 +118,7 @@ bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node) { int i = mTemporaryIndex; - out << mOutputHLSL->typeString(node->getType()) << " s" << i << ";\n"; + out << TypeString(node->getType()) << " s" << i << ";\n"; out << "{\n"; diff --git a/src/3rdparty/angle/src/compiler/translator/Uniform.cpp b/src/3rdparty/angle/src/compiler/translator/Uniform.cpp deleted file mode 100644 index 922e13f071..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Uniform.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/Uniform.h" - -namespace sh -{ - -Uniform::Uniform(GLenum type, GLenum precision, const char *name, int arraySize, int registerIndex) -{ - this->type = type; - this->precision = precision; - this->name = name; - this->arraySize = arraySize; - this->registerIndex = registerIndex; -} - -} diff --git a/src/3rdparty/angle/src/compiler/translator/Uniform.h b/src/3rdparty/angle/src/compiler/translator/Uniform.h deleted file mode 100644 index 4c53ffa7d2..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/Uniform.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef COMPILER_UNIFORM_H_ -#define COMPILER_UNIFORM_H_ - -#include -#include - -#define GL_APICALL -#include - -namespace sh -{ - -struct Uniform -{ - Uniform(GLenum type, GLenum precision, const char *name, int arraySize, int registerIndex); - - GLenum type; - GLenum precision; - std::string name; - unsigned int arraySize; - - int registerIndex; -}; - -typedef std::vector ActiveUniforms; - -} - -#endif // COMPILER_UNIFORM_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp new file mode 100644 index 0000000000..41a7d2c10b --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp @@ -0,0 +1,291 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// UniformHLSL.cpp: +// Methods for GLSL to HLSL translation for uniforms and interface blocks. +// + +#include "OutputHLSL.h" +#include "common/blocklayout.h" +#include "common/utilities.h" +#include "compiler/translator/UniformHLSL.h" +#include "compiler/translator/StructureHLSL.h" +#include "compiler/translator/util.h" +#include "compiler/translator/UtilsHLSL.h" + +namespace sh +{ + +static const char *UniformRegisterPrefix(const TType &type) +{ + if (IsSampler(type.getBasicType())) + { + return "s"; + } + else + { + return "c"; + } +} + +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(); + const TLayoutMatrixPacking matrixPacking = fieldType.getLayoutQualifier().matrixPacking; + ASSERT(matrixPacking != EmpUnspecified); + TStructure *structure = fieldType.getStruct(); + + if (fieldType.isMatrix()) + { + // Use HLSL row-major packing for GLSL column-major matrices + const TString &matrixPackString = (matrixPacking == EmpRowMajor ? "column_major" : "row_major"); + return matrixPackString + " " + TypeString(fieldType); + } + else if (structure) + { + // Use HLSL row-major packing for GLSL column-major matrices + return QualifiedStructNameString(*structure, matrixPacking == EmpColumnMajor, + blockStorage == EbsStd140); + } + else + { + return TypeString(fieldType); + } +} + +static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock) +{ + return DecoratePrivate(interfaceBlock.name()) + "_type"; +} + +UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType) + : mUniformRegister(0), + mInterfaceBlockRegister(0), + mSamplerRegister(0), + mStructureHLSL(structureHLSL), + mOutputType(outputType) +{} + +void UniformHLSL::reserveUniformRegisters(unsigned int registerCount) +{ + mUniformRegister = registerCount; +} + +void UniformHLSL::reserveInterfaceBlockRegisters(unsigned int registerCount) +{ + mInterfaceBlockRegister = registerCount; +} + +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 sh::Uniform &activeUniform = mActiveUniforms.back(); + mUniformRegisterMap[activeUniform.name] = registerIndex; + + unsigned int registerCount = HLSLVariableRegisterCount(activeUniform, mOutputType); + if (IsSampler(type.getBasicType())) + { + mSamplerRegister += registerCount; + } + else + { + mUniformRegister += registerCount; + } + + return registerIndex; +} + +TString UniformHLSL::uniformsHeader(ShShaderOutput outputType, const ReferencedSymbols &referencedUniforms) +{ + TString uniforms; + + for (ReferencedSymbols::const_iterator uniformIt = referencedUniforms.begin(); + uniformIt != referencedUniforms.end(); uniformIt++) + { + const TIntermSymbol &uniform = *uniformIt->second; + const TType &type = uniform.getType(); + const TString &name = uniform.getSymbol(); + + unsigned int registerIndex = declareUniformAndAssignRegister(type, name); + + if (outputType == SH_HLSL11_OUTPUT && IsSampler(type.getBasicType())) // Also declare the texture + { + uniforms += "uniform " + SamplerString(type) + " sampler_" + DecorateUniform(name, type) + ArrayString(type) + + " : register(s" + str(registerIndex) + ");\n"; + + uniforms += "uniform " + TextureString(type) + " texture_" + DecorateUniform(name, type) + ArrayString(type) + + " : register(t" + str(registerIndex) + ");\n"; + } + else + { + const TStructure *structure = type.getStruct(); + const TString &typeName = (structure ? QualifiedStructNameString(*structure, false, false) : TypeString(type)); + + const TString ®isterString = TString("register(") + UniformRegisterPrefix(type) + str(registerIndex) + ")"; + + uniforms += "uniform " + typeName + " " + DecorateUniform(name, type) + ArrayString(type) + " : " + registerString + ";\n"; + } + } + + return (uniforms.empty() ? "" : ("// Uniforms\n\n" + uniforms)); +} + +TString UniformHLSL::interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks) +{ + TString interfaceBlocks; + + for (ReferencedSymbols::const_iterator interfaceBlockIt = referencedInterfaceBlocks.begin(); + interfaceBlockIt != referencedInterfaceBlocks.end(); interfaceBlockIt++) + { + 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; + mInterfaceBlockRegister += std::max(1u, arraySize); + + activeBlock.layout = GetBlockLayoutType(interfaceBlock.blockStorage()); + + if (interfaceBlock.matrixPacking() == EmpRowMajor) + { + activeBlock.isRowMajorLayout = true; + } + + mActiveInterfaceBlocks.push_back(activeBlock); + + if (interfaceBlock.hasInstanceName()) + { + interfaceBlocks += interfaceBlockStructString(interfaceBlock); + } + + if (arraySize > 0) + { + for (unsigned int arrayIndex = 0; arrayIndex < arraySize; arrayIndex++) + { + interfaceBlocks += interfaceBlockString(interfaceBlock, activeRegister + arrayIndex, arrayIndex); + } + } + else + { + interfaceBlocks += interfaceBlockString(interfaceBlock, activeRegister, GL_INVALID_INDEX); + } + } + + return (interfaceBlocks.empty() ? "" : ("// Interface Blocks\n\n" + interfaceBlocks)); +} + +TString UniformHLSL::interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex) +{ + const TString &arrayIndexString = (arrayIndex != GL_INVALID_INDEX ? Decorate(str(arrayIndex)) : ""); + const TString &blockName = interfaceBlock.name() + arrayIndexString; + TString hlsl; + + hlsl += "cbuffer " + blockName + " : register(b" + str(registerIndex) + ")\n" + "{\n"; + + if (interfaceBlock.hasInstanceName()) + { + hlsl += " " + InterfaceBlockStructName(interfaceBlock) + " " + + interfaceBlockInstanceString(interfaceBlock, arrayIndex) + ";\n"; + } + else + { + const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage(); + hlsl += interfaceBlockMembersString(interfaceBlock, blockStorage); + } + + hlsl += "};\n\n"; + + return hlsl; +} + +TString UniformHLSL::interfaceBlockInstanceString(const TInterfaceBlock& interfaceBlock, unsigned int arrayIndex) +{ + if (!interfaceBlock.hasInstanceName()) + { + return ""; + } + else if (interfaceBlock.isArray()) + { + return DecoratePrivate(interfaceBlock.instanceName()) + "_" + str(arrayIndex); + } + else + { + return Decorate(interfaceBlock.instanceName()); + } +} + +TString UniformHLSL::interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage) +{ + TString hlsl; + + Std140PaddingHelper padHelper = mStructureHLSL->getPaddingHelper(); + + for (unsigned int typeIndex = 0; typeIndex < interfaceBlock.fields().size(); typeIndex++) + { + const TField &field = *interfaceBlock.fields()[typeIndex]; + const TType &fieldType = *field.type(); + + if (blockStorage == EbsStd140) + { + // 2 and 3 component vector types in some cases need pre-padding + hlsl += padHelper.prePadding(fieldType); + } + + hlsl += " " + InterfaceBlockFieldTypeString(field, blockStorage) + + " " + Decorate(field.name()) + ArrayString(fieldType) + ";\n"; + + // must pad out after matrices and arrays, where HLSL usually allows itself room to pack stuff + if (blockStorage == EbsStd140) + { + const bool useHLSLRowMajorPacking = (fieldType.getLayoutQualifier().matrixPacking == EmpColumnMajor); + hlsl += padHelper.postPaddingString(fieldType, useHLSLRowMajorPacking); + } + } + + return hlsl; +} + +TString UniformHLSL::interfaceBlockStructString(const TInterfaceBlock &interfaceBlock) +{ + const TLayoutBlockStorage blockStorage = interfaceBlock.blockStorage(); + + return "struct " + InterfaceBlockStructName(interfaceBlock) + "\n" + "{\n" + + interfaceBlockMembersString(interfaceBlock, blockStorage) + + "};\n\n"; +} + +} diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h new file mode 100644 index 0000000000..835b1ef2c8 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h @@ -0,0 +1,66 @@ +// +// 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. +// +// UniformHLSL.h: +// Methods for GLSL to HLSL translation for uniforms and interface blocks. +// + +#ifndef TRANSLATOR_UNIFORMHLSL_H_ +#define TRANSLATOR_UNIFORMHLSL_H_ + +#include "common/shadervars.h" +#include "compiler/translator/Types.h" + +namespace sh +{ +class StructureHLSL; + +class UniformHLSL +{ + public: + UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType); + + void reserveUniformRegisters(unsigned int registerCount); + void reserveInterfaceBlockRegisters(unsigned int registerCount); + TString uniformsHeader(ShShaderOutput outputType, const ReferencedSymbols &referencedUniforms); + TString interfaceBlocksHeader(const ReferencedSymbols &referencedInterfaceBlocks); + + // 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; + } + const std::map &getUniformRegisterMap() const + { + return mUniformRegisterMap; + } + + private: + TString interfaceBlockString(const TInterfaceBlock &interfaceBlock, unsigned int registerIndex, unsigned int arrayIndex); + TString interfaceBlockMembersString(const TInterfaceBlock &interfaceBlock, TLayoutBlockStorage blockStorage); + TString interfaceBlockStructString(const TInterfaceBlock &interfaceBlock); + + // Returns the uniform's register index + unsigned int declareUniformAndAssignRegister(const TType &type, const TString &name); + + unsigned int mUniformRegister; + unsigned int mInterfaceBlockRegister; + unsigned int mSamplerRegister; + StructureHLSL *mStructureHLSL; + ShShaderOutput mOutputType; + + std::vector mActiveUniforms; + std::vector mActiveInterfaceBlocks; + std::map mInterfaceBlockRegisterMap; + std::map mUniformRegisterMap; +}; + +} + +#endif // TRANSLATOR_UNIFORMHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp new file mode 100644 index 0000000000..de0c36ca65 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp @@ -0,0 +1,243 @@ +// +// 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. +// +// UtilsHLSL.cpp: +// Utility methods for GLSL to HLSL translation. +// + +#include "compiler/translator/UtilsHLSL.h" +#include "compiler/translator/StructureHLSL.h" +#include "compiler/translator/SymbolTable.h" + +namespace sh +{ + +TString SamplerString(const TType &type) +{ + if (IsShadowSampler(type.getBasicType())) + { + return "SamplerComparisonState"; + } + else + { + return "SamplerState"; + } +} + +TString TextureString(const TType &type) +{ + switch (type.getBasicType()) + { + case EbtSampler2D: return "Texture2D"; + case EbtSamplerCube: return "TextureCube"; + case EbtSamplerExternalOES: return "Texture2D"; + case EbtSampler2DArray: return "Texture2DArray"; + case EbtSampler3D: return "Texture3D"; + case EbtISampler2D: return "Texture2D"; + case EbtISampler3D: return "Texture3D"; + case EbtISamplerCube: return "Texture2DArray"; + case EbtISampler2DArray: return "Texture2DArray"; + case EbtUSampler2D: return "Texture2D"; + case EbtUSampler3D: return "Texture3D"; + case EbtUSamplerCube: return "Texture2DArray"; + case EbtUSampler2DArray: return "Texture2DArray"; + case EbtSampler2DShadow: return "Texture2D"; + case EbtSamplerCubeShadow: return "TextureCube"; + case EbtSampler2DArrayShadow: return "Texture2DArray"; + default: UNREACHABLE(); + } + + return ""; +} + +TString DecorateUniform(const TString &string, const TType &type) +{ + if (type.getBasicType() == EbtSamplerExternalOES) + { + return "ex_" + string; + } + + return Decorate(string); +} + +TString DecorateField(const TString &string, const TStructure &structure) +{ + if (structure.name().compare(0, 3, "gl_") != 0) + { + return Decorate(string); + } + + return string; +} + +TString DecoratePrivate(const TString &privateText) +{ + return "dx_" + privateText; +} + +TString Decorate(const TString &string) +{ + if (string.compare(0, 3, "gl_") != 0) + { + return "_" + string; + } + + return string; +} + +TString TypeString(const TType &type) +{ + const TStructure* structure = type.getStruct(); + if (structure) + { + const TString& typeName = structure->name(); + if (typeName != "") + { + return StructNameString(*structure); + } + else // Nameless structure, define in place + { + return StructureHLSL::defineNameless(*structure); + } + } + else if (type.isMatrix()) + { + int cols = type.getCols(); + int rows = type.getRows(); + return "float" + str(cols) + "x" + str(rows); + } + else + { + switch (type.getBasicType()) + { + case EbtFloat: + switch (type.getNominalSize()) + { + case 1: return "float"; + case 2: return "float2"; + case 3: return "float3"; + case 4: return "float4"; + } + case EbtInt: + switch (type.getNominalSize()) + { + case 1: return "int"; + case 2: return "int2"; + case 3: return "int3"; + case 4: return "int4"; + } + case EbtUInt: + switch (type.getNominalSize()) + { + case 1: return "uint"; + case 2: return "uint2"; + case 3: return "uint3"; + case 4: return "uint4"; + } + case EbtBool: + switch (type.getNominalSize()) + { + case 1: return "bool"; + case 2: return "bool2"; + case 3: return "bool3"; + case 4: return "bool4"; + } + case EbtVoid: + return "void"; + case EbtSampler2D: + case EbtISampler2D: + case EbtUSampler2D: + case EbtSampler2DArray: + case EbtISampler2DArray: + case EbtUSampler2DArray: + return "sampler2D"; + case EbtSamplerCube: + case EbtISamplerCube: + case EbtUSamplerCube: + return "samplerCUBE"; + case EbtSamplerExternalOES: + return "sampler2D"; + default: + break; + } + } + + UNREACHABLE(); + return ""; +} + +TString StructNameString(const TStructure &structure) +{ + if (structure.name().empty()) + { + return ""; + } + + return "ss" + str(structure.uniqueId()) + "_" + structure.name(); +} + +TString QualifiedStructNameString(const TStructure &structure, bool useHLSLRowMajorPacking, + bool useStd140Packing) +{ + if (structure.name() == "") + { + return ""; + } + + TString prefix = ""; + + // Structs packed with row-major matrices in HLSL are prefixed with "rm" + // GLSL column-major maps to HLSL row-major, and the converse is true + + if (useStd140Packing) + { + prefix += "std_"; + } + + if (useHLSLRowMajorPacking) + { + prefix += "rm_"; + } + + return prefix + StructNameString(structure); +} + +TString InterpolationString(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqVaryingIn: return ""; + case EvqFragmentIn: return ""; + case EvqInvariantVaryingIn: return ""; + case EvqSmoothIn: return "linear"; + case EvqFlatIn: return "nointerpolation"; + case EvqCentroidIn: return "centroid"; + case EvqVaryingOut: return ""; + case EvqVertexOut: return ""; + case EvqInvariantVaryingOut: return ""; + case EvqSmoothOut: return "linear"; + case EvqFlatOut: return "nointerpolation"; + case EvqCentroidOut: return "centroid"; + default: UNREACHABLE(); + } + + return ""; +} + +TString QualifierString(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqIn: return "in"; + case EvqOut: return "inout"; // 'out' results in an HLSL error if not all fields are written, for GLSL it's undefined + case EvqInOut: return "inout"; + case EvqConstReadOnly: return "const"; + default: UNREACHABLE(); + } + + return ""; +} + +} diff --git a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h new file mode 100644 index 0000000000..aaa3ddf5d2 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h @@ -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. +// +// UtilsHLSL.h: +// Utility methods for GLSL to HLSL translation. +// + +#ifndef TRANSLATOR_UTILSHLSL_H_ +#define TRANSLATOR_UTILSHLSL_H_ + +#include +#include "compiler/translator/Types.h" + +#include "angle_gl.h" + +namespace sh +{ + +TString TextureString(const TType &type); +TString SamplerString(const TType &type); +// Prepends an underscore to avoid naming clashes +TString Decorate(const TString &string); +TString DecorateUniform(const TString &string, const TType &type); +TString DecorateField(const TString &string, const TStructure &structure); +TString DecoratePrivate(const TString &privateText); +TString TypeString(const TType &type); +TString StructNameString(const TStructure &structure); +TString QualifiedStructNameString(const TStructure &structure, bool useHLSLRowMajorPacking, + bool useStd140Packing); +TString InterpolationString(TQualifier qualifier); +TString QualifierString(TQualifier qualifier); + +} + +#endif // TRANSLATOR_UTILSHLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp index 3c2cc41cda..c1a7b7524f 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp +++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -8,26 +8,10 @@ #include "compiler/translator/InfoSink.h" #include "compiler/translator/InitializeParseContext.h" #include "compiler/translator/ParseContext.h" +#include "angle_gl.h" -namespace { -bool IsLoopIndex(const TIntermSymbol* symbol, const TLoopStack& stack) { - for (TLoopStack::const_iterator i = stack.begin(); i != stack.end(); ++i) { - if (i->index.id == symbol->getId()) - return true; - } - return false; -} - -void MarkLoopForUnroll(const TIntermSymbol* symbol, TLoopStack& stack) { - for (TLoopStack::iterator i = stack.begin(); i != stack.end(); ++i) { - if (i->index.id == symbol->getId()) { - ASSERT(i->loop != NULL); - i->loop->setUnrollFlag(true); - return; - } - } - UNREACHABLE(); -} +namespace +{ // Traverses a node to check if it represents a constant index expression. // Definition: @@ -38,110 +22,146 @@ void MarkLoopForUnroll(const TIntermSymbol* symbol, TLoopStack& stack) { // - Constant expressions // - Loop indices as defined in section 4 // - Expressions composed of both of the above -class ValidateConstIndexExpr : public TIntermTraverser { -public: - ValidateConstIndexExpr(const TLoopStack& stack) +class ValidateConstIndexExpr : public TIntermTraverser +{ + public: + ValidateConstIndexExpr(TLoopStack& stack) : mValid(true), mLoopStack(stack) {} // Returns true if the parsed node represents a constant index expression. bool isValid() const { return mValid; } - virtual void visitSymbol(TIntermSymbol* symbol) { + virtual void visitSymbol(TIntermSymbol *symbol) + { // Only constants and loop indices are allowed in a // constant index expression. - if (mValid) { + if (mValid) + { mValid = (symbol->getQualifier() == EvqConst) || - IsLoopIndex(symbol, mLoopStack); + (mLoopStack.findLoop(symbol)); } } -private: + private: bool mValid; - const TLoopStack& mLoopStack; + TLoopStack& mLoopStack; }; -// Traverses a node to check if it uses a loop index. -// If an int loop index is used in its body as a sampler array index, -// mark the loop for unroll. -class ValidateLoopIndexExpr : public TIntermTraverser { -public: - ValidateLoopIndexExpr(TLoopStack& stack) - : mUsesFloatLoopIndex(false), - mUsesIntLoopIndex(false), - mLoopStack(stack) {} - - bool usesFloatLoopIndex() const { return mUsesFloatLoopIndex; } - bool usesIntLoopIndex() const { return mUsesIntLoopIndex; } - - virtual void visitSymbol(TIntermSymbol* symbol) { - if (IsLoopIndex(symbol, mLoopStack)) { - switch (symbol->getBasicType()) { - case EbtFloat: - mUsesFloatLoopIndex = true; - break; - case EbtInt: - mUsesIntLoopIndex = true; - MarkLoopForUnroll(symbol, mLoopStack); - break; - default: - UNREACHABLE(); - } - } +const char *GetOperatorString(TOperator op) +{ + switch (op) + { + case EOpInitialize: return "="; + case EOpAssign: return "="; + case EOpAddAssign: return "+="; + case EOpSubAssign: return "-="; + case EOpDivAssign: return "/="; + + // Fall-through. + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: return "*="; + + // Fall-through. + case EOpIndexDirect: + case EOpIndexIndirect: return "[]"; + + case EOpIndexDirectStruct: + case EOpIndexDirectInterfaceBlock: return "."; + case EOpVectorSwizzle: return "."; + case EOpAdd: return "+"; + case EOpSub: return "-"; + case EOpMul: return "*"; + case EOpDiv: return "/"; + case EOpMod: UNIMPLEMENTED(); break; + case EOpEqual: return "=="; + case EOpNotEqual: return "!="; + case EOpLessThan: return "<"; + case EOpGreaterThan: return ">"; + case EOpLessThanEqual: return "<="; + case EOpGreaterThanEqual: return ">="; + + // Fall-through. + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: return "*"; + + case EOpLogicalOr: return "||"; + case EOpLogicalXor: return "^^"; + case EOpLogicalAnd: return "&&"; + case EOpNegative: return "-"; + case EOpVectorLogicalNot: return "not"; + case EOpLogicalNot: return "!"; + case EOpPostIncrement: return "++"; + case EOpPostDecrement: return "--"; + case EOpPreIncrement: return "++"; + case EOpPreDecrement: return "--"; + + case EOpRadians: return "radians"; + case EOpDegrees: return "degrees"; + case EOpSin: return "sin"; + case EOpCos: return "cos"; + case EOpTan: return "tan"; + case EOpAsin: return "asin"; + case EOpAcos: return "acos"; + case EOpAtan: return "atan"; + case EOpExp: return "exp"; + case EOpLog: return "log"; + case EOpExp2: return "exp2"; + case EOpLog2: return "log2"; + case EOpSqrt: return "sqrt"; + case EOpInverseSqrt: return "inversesqrt"; + case EOpAbs: return "abs"; + case EOpSign: return "sign"; + case EOpFloor: return "floor"; + case EOpCeil: return "ceil"; + case EOpFract: return "fract"; + case EOpLength: return "length"; + case EOpNormalize: return "normalize"; + case EOpDFdx: return "dFdx"; + case EOpDFdy: return "dFdy"; + case EOpFwidth: return "fwidth"; + case EOpAny: return "any"; + case EOpAll: return "all"; + + default: break; } + return ""; +} -private: - bool mUsesFloatLoopIndex; - bool mUsesIntLoopIndex; - TLoopStack& mLoopStack; -}; -} // namespace +} // namespace anonymous -ValidateLimitations::ValidateLimitations(ShShaderType shaderType, - TInfoSinkBase& sink) +ValidateLimitations::ValidateLimitations(sh::GLenum shaderType, + TInfoSinkBase &sink) : mShaderType(shaderType), mSink(sink), mNumErrors(0) { } -bool ValidateLimitations::visitBinary(Visit, TIntermBinary* node) +bool ValidateLimitations::visitBinary(Visit, TIntermBinary *node) { // Check if loop index is modified in the loop body. validateOperation(node, node->getLeft()); // Check indexing. - switch (node->getOp()) { + switch (node->getOp()) + { case EOpIndexDirect: - validateIndexing(node); - break; case EOpIndexIndirect: -#if defined(__APPLE__) - // Loop unrolling is a work-around for a Mac Cg compiler bug where it - // crashes when a sampler array's index is also the loop index. - // Once Apple fixes this bug, we should remove the code in this CL. - // See http://codereview.appspot.com/4331048/. - if ((node->getLeft() != NULL) && (node->getRight() != NULL) && - (node->getLeft()->getAsSymbolNode())) { - TIntermSymbol* symbol = node->getLeft()->getAsSymbolNode(); - if (IsSampler(symbol->getBasicType()) && symbol->isArray()) { - ValidateLoopIndexExpr validate(mLoopStack); - node->getRight()->traverse(&validate); - if (validate.usesFloatLoopIndex()) { - error(node->getLine(), - "sampler array index is float loop index", - "for"); - } - } - } -#endif validateIndexing(node); break; - default: break; + default: + break; } return true; } -bool ValidateLimitations::visitUnary(Visit, TIntermUnary* node) +bool ValidateLimitations::visitUnary(Visit, TIntermUnary *node) { // Check if loop index is modified in the loop body. validateOperation(node, node->getOperand()); @@ -149,7 +169,7 @@ bool ValidateLimitations::visitUnary(Visit, TIntermUnary* node) return true; } -bool ValidateLimitations::visitAggregate(Visit, TIntermAggregate* node) +bool ValidateLimitations::visitAggregate(Visit, TIntermAggregate *node) { switch (node->getOp()) { case EOpFunctionCall: @@ -161,22 +181,20 @@ bool ValidateLimitations::visitAggregate(Visit, TIntermAggregate* node) return true; } -bool ValidateLimitations::visitLoop(Visit, TIntermLoop* node) +bool ValidateLimitations::visitLoop(Visit, TIntermLoop *node) { if (!validateLoopType(node)) return false; - TLoopInfo info; - memset(&info, 0, sizeof(TLoopInfo)); - info.loop = node; - if (!validateForLoopHeader(node, &info)) + if (!validateForLoopHeader(node)) return false; - TIntermNode* body = node->getBody(); - if (body != NULL) { - mLoopStack.push_back(info); + TIntermNode *body = node->getBody(); + if (body != NULL) + { + mLoopStack.push(node); body->traverse(this); - mLoopStack.pop_back(); + mLoopStack.pop(); } // The loop is fully processed - no need to visit children. @@ -184,7 +202,7 @@ bool ValidateLimitations::visitLoop(Visit, TIntermLoop* node) } void ValidateLimitations::error(TSourceLoc loc, - const char *reason, const char* token) + const char *reason, const char *token) { mSink.prefix(EPrefixError); mSink.location(loc); @@ -197,12 +215,13 @@ bool ValidateLimitations::withinLoopBody() const return !mLoopStack.empty(); } -bool ValidateLimitations::isLoopIndex(const TIntermSymbol* symbol) const +bool ValidateLimitations::isLoopIndex(TIntermSymbol *symbol) { - return IsLoopIndex(symbol, mLoopStack); + return mLoopStack.findLoop(symbol) != NULL; } -bool ValidateLimitations::validateLoopType(TIntermLoop* node) { +bool ValidateLimitations::validateLoopType(TIntermLoop *node) +{ TLoopType type = node->getType(); if (type == ELoopFor) return true; @@ -214,8 +233,7 @@ bool ValidateLimitations::validateLoopType(TIntermLoop* node) { return false; } -bool ValidateLimitations::validateForLoopHeader(TIntermLoop* node, - TLoopInfo* info) +bool ValidateLimitations::validateForLoopHeader(TIntermLoop *node) { ASSERT(node->getType() == ELoopFor); @@ -223,74 +241,80 @@ bool ValidateLimitations::validateForLoopHeader(TIntermLoop* node, // The for statement has the form: // for ( init-declaration ; condition ; expression ) statement // - if (!validateForLoopInit(node, info)) + int indexSymbolId = validateForLoopInit(node); + if (indexSymbolId < 0) return false; - if (!validateForLoopCond(node, info)) + if (!validateForLoopCond(node, indexSymbolId)) return false; - if (!validateForLoopExpr(node, info)) + if (!validateForLoopExpr(node, indexSymbolId)) return false; return true; } -bool ValidateLimitations::validateForLoopInit(TIntermLoop* node, - TLoopInfo* info) +int ValidateLimitations::validateForLoopInit(TIntermLoop *node) { - TIntermNode* init = node->getInit(); - if (init == NULL) { + TIntermNode *init = node->getInit(); + if (init == NULL) + { error(node->getLine(), "Missing init declaration", "for"); - return false; + return -1; } // // init-declaration has the form: // type-specifier identifier = constant-expression // - TIntermAggregate* decl = init->getAsAggregate(); - if ((decl == NULL) || (decl->getOp() != EOpDeclaration)) { + TIntermAggregate *decl = init->getAsAggregate(); + if ((decl == NULL) || (decl->getOp() != EOpDeclaration)) + { error(init->getLine(), "Invalid init declaration", "for"); - return false; + return -1; } // To keep things simple do not allow declaration list. - TIntermSequence& declSeq = decl->getSequence(); - if (declSeq.size() != 1) { + TIntermSequence *declSeq = decl->getSequence(); + if (declSeq->size() != 1) + { error(decl->getLine(), "Invalid init declaration", "for"); - return false; + return -1; } - TIntermBinary* declInit = declSeq[0]->getAsBinaryNode(); - if ((declInit == NULL) || (declInit->getOp() != EOpInitialize)) { + TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); + if ((declInit == NULL) || (declInit->getOp() != EOpInitialize)) + { error(decl->getLine(), "Invalid init declaration", "for"); - return false; + return -1; } - TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode(); - if (symbol == NULL) { + TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); + if (symbol == NULL) + { error(declInit->getLine(), "Invalid init declaration", "for"); - return false; + return -1; } // The loop index has type int or float. TBasicType type = symbol->getBasicType(); - if ((type != EbtInt) && (type != EbtFloat)) { + if ((type != EbtInt) && (type != EbtUInt) && (type != EbtFloat)) { error(symbol->getLine(), "Invalid type for loop index", getBasicString(type)); - return false; + return -1; } // The loop index is initialized with constant expression. - if (!isConstExpr(declInit->getRight())) { + if (!isConstExpr(declInit->getRight())) + { error(declInit->getLine(), "Loop index cannot be initialized with non-constant expression", symbol->getSymbol().c_str()); - return false; + return -1; } - info->index.id = symbol->getId(); - return true; + return symbol->getId(); } -bool ValidateLimitations::validateForLoopCond(TIntermLoop* node, - TLoopInfo* info) +bool ValidateLimitations::validateForLoopCond(TIntermLoop *node, + int indexSymbolId) { - TIntermNode* cond = node->getCondition(); - if (cond == NULL) { + TIntermNode *cond = node->getCondition(); + if (cond == NULL) + { error(node->getLine(), "Missing condition", "for"); return false; } @@ -298,24 +322,28 @@ bool ValidateLimitations::validateForLoopCond(TIntermLoop* node, // condition has the form: // loop_index relational_operator constant_expression // - TIntermBinary* binOp = cond->getAsBinaryNode(); - if (binOp == NULL) { + TIntermBinary *binOp = cond->getAsBinaryNode(); + if (binOp == NULL) + { error(node->getLine(), "Invalid condition", "for"); return false; } // Loop index should be to the left of relational operator. - TIntermSymbol* symbol = binOp->getLeft()->getAsSymbolNode(); - if (symbol == NULL) { + TIntermSymbol *symbol = binOp->getLeft()->getAsSymbolNode(); + if (symbol == NULL) + { error(binOp->getLine(), "Invalid condition", "for"); return false; } - if (symbol->getId() != info->index.id) { + if (symbol->getId() != indexSymbolId) + { error(symbol->getLine(), "Expected loop index", symbol->getSymbol().c_str()); return false; } // Relational operator is one of: > >= < <= == or !=. - switch (binOp->getOp()) { + switch (binOp->getOp()) + { case EOpEqual: case EOpNotEqual: case EOpLessThan: @@ -326,11 +354,12 @@ bool ValidateLimitations::validateForLoopCond(TIntermLoop* node, default: error(binOp->getLine(), "Invalid relational operator", - getOperatorString(binOp->getOp())); + GetOperatorString(binOp->getOp())); break; } // Loop index must be compared with a constant. - if (!isConstExpr(binOp->getRight())) { + if (!isConstExpr(binOp->getRight())) + { error(binOp->getLine(), "Loop index cannot be compared with non-constant expression", symbol->getSymbol().c_str()); @@ -340,11 +369,12 @@ bool ValidateLimitations::validateForLoopCond(TIntermLoop* node, return true; } -bool ValidateLimitations::validateForLoopExpr(TIntermLoop* node, - TLoopInfo* info) +bool ValidateLimitations::validateForLoopExpr(TIntermLoop *node, + int indexSymbolId) { - TIntermNode* expr = node->getExpression(); - if (expr == NULL) { + TIntermNode *expr = node->getExpression(); + if (expr == NULL) + { error(node->getLine(), "Missing expression", "for"); return false; } @@ -358,50 +388,58 @@ bool ValidateLimitations::validateForLoopExpr(TIntermLoop* node, // --loop_index // The last two forms are not specified in the spec, but I am assuming // its an oversight. - TIntermUnary* unOp = expr->getAsUnaryNode(); - TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode(); + TIntermUnary *unOp = expr->getAsUnaryNode(); + TIntermBinary *binOp = unOp ? NULL : expr->getAsBinaryNode(); TOperator op = EOpNull; - TIntermSymbol* symbol = NULL; - if (unOp != NULL) { + TIntermSymbol *symbol = NULL; + if (unOp != NULL) + { op = unOp->getOp(); symbol = unOp->getOperand()->getAsSymbolNode(); - } else if (binOp != NULL) { + } + else if (binOp != NULL) + { op = binOp->getOp(); symbol = binOp->getLeft()->getAsSymbolNode(); } // The operand must be loop index. - if (symbol == NULL) { + if (symbol == NULL) + { error(expr->getLine(), "Invalid expression", "for"); return false; } - if (symbol->getId() != info->index.id) { + if (symbol->getId() != indexSymbolId) + { error(symbol->getLine(), "Expected loop index", symbol->getSymbol().c_str()); return false; } // The operator is one of: ++ -- += -=. - switch (op) { - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - ASSERT((unOp != NULL) && (binOp == NULL)); - break; - case EOpAddAssign: - case EOpSubAssign: - ASSERT((unOp == NULL) && (binOp != NULL)); - break; - default: - error(expr->getLine(), "Invalid operator", getOperatorString(op)); - return false; + switch (op) + { + case EOpPostIncrement: + case EOpPostDecrement: + case EOpPreIncrement: + case EOpPreDecrement: + ASSERT((unOp != NULL) && (binOp == NULL)); + break; + case EOpAddAssign: + case EOpSubAssign: + ASSERT((unOp == NULL) && (binOp != NULL)); + break; + default: + error(expr->getLine(), "Invalid operator", GetOperatorString(op)); + return false; } // Loop index must be incremented/decremented with a constant. - if (binOp != NULL) { - if (!isConstExpr(binOp->getRight())) { + if (binOp != NULL) + { + if (!isConstExpr(binOp->getRight())) + { error(binOp->getLine(), "Loop index cannot be modified by non-constant expression", symbol->getSymbol().c_str()); @@ -412,7 +450,7 @@ bool ValidateLimitations::validateForLoopExpr(TIntermLoop* node, return true; } -bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) +bool ValidateLimitations::validateFunctionCall(TIntermAggregate *node) { ASSERT(node->getOp() == EOpFunctionCall); @@ -423,9 +461,10 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) // List of param indices for which loop indices are used as argument. typedef std::vector ParamIndex; ParamIndex pIndex; - TIntermSequence& params = node->getSequence(); - for (TIntermSequence::size_type i = 0; i < params.size(); ++i) { - TIntermSymbol* symbol = params[i]->getAsSymbolNode(); + TIntermSequence *params = node->getSequence(); + for (TIntermSequence::size_type i = 0; i < params->size(); ++i) + { + TIntermSymbol *symbol = (*params)[i]->getAsSymbolNode(); if (symbol && isLoopIndex(symbol)) pIndex.push_back(i); } @@ -436,17 +475,19 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) bool valid = true; TSymbolTable& symbolTable = GetGlobalParseContext()->symbolTable; - TSymbol* symbol = symbolTable.find(node->getName()); + TSymbol* symbol = symbolTable.find(node->getName(), GetGlobalParseContext()->shaderVersion); ASSERT(symbol && symbol->isFunction()); - TFunction* function = static_cast(symbol); + TFunction *function = static_cast(symbol); for (ParamIndex::const_iterator i = pIndex.begin(); - i != pIndex.end(); ++i) { - const TParameter& param = function->getParam(*i); + i != pIndex.end(); ++i) + { + const TParameter ¶m = function->getParam(*i); TQualifier qual = param.type->getQualifier(); - if ((qual == EvqOut) || (qual == EvqInOut)) { - error(params[*i]->getLine(), + if ((qual == EvqOut) || (qual == EvqInOut)) + { + error((*params)[*i]->getLine(), "Loop index cannot be used as argument to a function out or inout parameter", - params[*i]->getAsSymbolNode()->getSymbol().c_str()); + (*params)[*i]->getAsSymbolNode()->getSymbol().c_str()); valid = false; } } @@ -454,14 +495,16 @@ bool ValidateLimitations::validateFunctionCall(TIntermAggregate* node) return valid; } -bool ValidateLimitations::validateOperation(TIntermOperator* node, - TIntermNode* operand) { +bool ValidateLimitations::validateOperation(TIntermOperator *node, + TIntermNode* operand) +{ // Check if loop index is modified in the loop body. if (!withinLoopBody() || !node->isAssignment()) return true; - const TIntermSymbol* symbol = operand->getAsSymbolNode(); - if (symbol && isLoopIndex(symbol)) { + TIntermSymbol *symbol = operand->getAsSymbolNode(); + if (symbol && isLoopIndex(symbol)) + { error(node->getLine(), "Loop index cannot be statically assigned to within the body of the loop", symbol->getSymbol().c_str()); @@ -469,13 +512,13 @@ bool ValidateLimitations::validateOperation(TIntermOperator* node, return true; } -bool ValidateLimitations::isConstExpr(TIntermNode* node) +bool ValidateLimitations::isConstExpr(TIntermNode *node) { ASSERT(node != NULL); return node->getAsConstantUnion() != NULL; } -bool ValidateLimitations::isConstIndexExpr(TIntermNode* node) +bool ValidateLimitations::isConstIndexExpr(TIntermNode *node) { ASSERT(node != NULL); @@ -484,15 +527,15 @@ bool ValidateLimitations::isConstIndexExpr(TIntermNode* node) return validate.isValid(); } -bool ValidateLimitations::validateIndexing(TIntermBinary* node) +bool ValidateLimitations::validateIndexing(TIntermBinary *node) { ASSERT((node->getOp() == EOpIndexDirect) || (node->getOp() == EOpIndexIndirect)); bool valid = true; - TIntermTyped* index = node->getRight(); + TIntermTyped *index = node->getRight(); // The index expression must have integral type. - if (!index->isScalar() || (index->getBasicType() != EbtInt)) { + if (!index->isScalarInt()) { error(index->getLine(), "Index expression must have integral type", index->getCompleteString().c_str()); @@ -500,10 +543,11 @@ bool ValidateLimitations::validateIndexing(TIntermBinary* node) } // The index expession must be a constant-index-expression unless // the operand is a uniform in a vertex shader. - TIntermTyped* operand = node->getLeft(); - bool skip = (mShaderType == SH_VERTEX_SHADER) && + TIntermTyped *operand = node->getLeft(); + bool skip = (mShaderType == GL_VERTEX_SHADER) && (operand->getQualifier() == EvqUniform); - if (!skip && !isConstIndexExpr(index)) { + if (!skip && !isConstIndexExpr(index)) + { error(index->getLine(), "Index expression must be constant", "[]"); valid = false; } diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h index 8839dd8b8a..8c9ebf53ed 100644 --- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h +++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h @@ -4,55 +4,51 @@ // found in the LICENSE file. // -#include "GLSLANG/ShaderLang.h" #include "compiler/translator/intermediate.h" +#include "compiler/translator/LoopInfo.h" class TInfoSinkBase; -struct TLoopInfo { - struct TIndex { - int id; // symbol id. - } index; - TIntermLoop* loop; -}; -typedef TVector TLoopStack; - // Traverses intermediate tree to ensure that the shader does not exceed the // minimum functionality mandated in GLSL 1.0 spec, Appendix A. -class ValidateLimitations : public TIntermTraverser { -public: - ValidateLimitations(ShShaderType shaderType, TInfoSinkBase& sink); +class ValidateLimitations : public TIntermTraverser +{ + public: + ValidateLimitations(sh::GLenum shaderType, TInfoSinkBase &sink); int numErrors() const { return mNumErrors; } - virtual bool visitBinary(Visit, TIntermBinary*); - virtual bool visitUnary(Visit, TIntermUnary*); - virtual bool visitAggregate(Visit, TIntermAggregate*); - virtual bool visitLoop(Visit, TIntermLoop*); + virtual bool visitBinary(Visit, TIntermBinary *); + virtual bool visitUnary(Visit, TIntermUnary *); + virtual bool visitAggregate(Visit, TIntermAggregate *); + virtual bool visitLoop(Visit, TIntermLoop *); -private: - void error(TSourceLoc loc, const char *reason, const char* token); + private: + void error(TSourceLoc loc, const char *reason, const char *token); bool withinLoopBody() const; - bool isLoopIndex(const TIntermSymbol* symbol) const; - bool validateLoopType(TIntermLoop* node); - bool validateForLoopHeader(TIntermLoop* node, TLoopInfo* info); - bool validateForLoopInit(TIntermLoop* node, TLoopInfo* info); - bool validateForLoopCond(TIntermLoop* node, TLoopInfo* info); - bool validateForLoopExpr(TIntermLoop* node, TLoopInfo* info); + bool isLoopIndex(TIntermSymbol *symbol); + bool validateLoopType(TIntermLoop *node); + + bool validateForLoopHeader(TIntermLoop *node); + // If valid, return the index symbol id; Otherwise, return -1. + int validateForLoopInit(TIntermLoop *node); + bool validateForLoopCond(TIntermLoop *node, int indexSymbolId); + bool validateForLoopExpr(TIntermLoop *node, int indexSymbolId); + // Returns true if none of the loop indices is used as the argument to // the given function out or inout parameter. - bool validateFunctionCall(TIntermAggregate* node); - bool validateOperation(TIntermOperator* node, TIntermNode* operand); + bool validateFunctionCall(TIntermAggregate *node); + bool validateOperation(TIntermOperator *node, TIntermNode *operand); // Returns true if indexing does not exceed the minimum functionality // mandated in GLSL 1.0 spec, Appendix A, Section 5. - bool isConstExpr(TIntermNode* node); - bool isConstIndexExpr(TIntermNode* node); - bool validateIndexing(TIntermBinary* node); + bool isConstExpr(TIntermNode *node); + bool isConstIndexExpr(TIntermNode *node); + bool validateIndexing(TIntermBinary *node); - ShShaderType mShaderType; - TInfoSinkBase& mSink; + sh::GLenum mShaderType; + TInfoSinkBase &mSink; int mNumErrors; TLoopStack mLoopStack; }; diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp new file mode 100644 index 0000000000..ac1c10d6b0 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.cpp @@ -0,0 +1,78 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/ValidateOutputs.h" +#include "compiler/translator/InfoSink.h" +#include "compiler/translator/InitializeParseContext.h" +#include "compiler/translator/ParseContext.h" + +ValidateOutputs::ValidateOutputs(TInfoSinkBase& sink, int maxDrawBuffers) + : mSink(sink), + mMaxDrawBuffers(maxDrawBuffers), + mNumErrors(0), + mHasUnspecifiedOutputLocation(false) +{ +} + +void ValidateOutputs::visitSymbol(TIntermSymbol *symbol) +{ + TString name = symbol->getSymbol(); + TQualifier qualifier = symbol->getQualifier(); + + if (mVisitedSymbols.count(name) == 1) + return; + + mVisitedSymbols.insert(name); + + if (qualifier == EvqFragmentOut) + { + const TType &type = symbol->getType(); + const int location = type.getLayoutQualifier().location; + + if (mHasUnspecifiedOutputLocation) + { + error(symbol->getLine(), "must explicitly specify all locations when using multiple fragment outputs", name.c_str()); + } + else if (location == -1) + { + mHasUnspecifiedOutputLocation = true; + } + else + { + OutputMap::iterator mapEntry = mOutputMap.find(location); + if (mapEntry == mOutputMap.end()) + { + const int elementCount = type.isArray() ? type.getArraySize() : 1; + if (location + elementCount > mMaxDrawBuffers) + { + error(symbol->getLine(), "output location must be < MAX_DRAW_BUFFERS", name.c_str()); + } + + for (int elementIndex = 0; elementIndex < elementCount; elementIndex++) + { + const int offsetLocation = location + elementIndex; + mOutputMap[offsetLocation] = symbol; + } + } + else + { + std::stringstream strstr; + strstr << "conflicting output locations with previously defined output '" + << mapEntry->second->getSymbol() << "'"; + + error(symbol->getLine(), strstr.str().c_str(), name.c_str()); + } + } + } +} + +void ValidateOutputs::error(TSourceLoc loc, const char *reason, const char* token) +{ + mSink.prefix(EPrefixError); + mSink.location(loc); + mSink << "'" << token << "' : " << reason << "\n"; + mNumErrors++; +} diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h new file mode 100644 index 0000000000..e391ad9486 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h @@ -0,0 +1,33 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/intermediate.h" + +#include + +class TInfoSinkBase; + +class ValidateOutputs : public TIntermTraverser +{ + public: + ValidateOutputs(TInfoSinkBase& sink, int maxDrawBuffers); + + int numErrors() const { return mNumErrors; } + + virtual void visitSymbol(TIntermSymbol*); + + private: + TInfoSinkBase& mSink; + int mMaxDrawBuffers; + int mNumErrors; + bool mHasUnspecifiedOutputLocation; + + typedef std::map OutputMap; + OutputMap mOutputMap; + std::set mVisitedSymbols; + + void error(TSourceLoc loc, const char *reason, const char* token); +}; diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp index ef888aff11..153455c4f1 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp @@ -1,196 +1,115 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // +#include "angle_gl.h" #include "compiler/translator/VariableInfo.h" +#include "compiler/translator/util.h" +#include "common/utilities.h" -namespace { - -TString arrayBrackets(int index) -{ - TStringStream stream; - stream << "[" << index << "]"; - return stream.str(); -} - -// Returns the data type for an attribute, uniform, or varying. -ShDataType getVariableDataType(const TType& type) -{ - switch (type.getBasicType()) { - case EbtFloat: - if (type.isMatrix()) { - switch (type.getNominalSize()) { - case 2: return SH_FLOAT_MAT2; - case 3: return SH_FLOAT_MAT3; - case 4: return SH_FLOAT_MAT4; - default: UNREACHABLE(); - } - } else if (type.isVector()) { - switch (type.getNominalSize()) { - case 2: return SH_FLOAT_VEC2; - case 3: return SH_FLOAT_VEC3; - case 4: return SH_FLOAT_VEC4; - default: UNREACHABLE(); - } - } else { - return SH_FLOAT; - } - case EbtInt: - if (type.isMatrix()) { - UNREACHABLE(); - } else if (type.isVector()) { - switch (type.getNominalSize()) { - case 2: return SH_INT_VEC2; - case 3: return SH_INT_VEC3; - case 4: return SH_INT_VEC4; - default: UNREACHABLE(); - } - } else { - return SH_INT; - } - case EbtBool: - if (type.isMatrix()) { - UNREACHABLE(); - } else if (type.isVector()) { - switch (type.getNominalSize()) { - case 2: return SH_BOOL_VEC2; - case 3: return SH_BOOL_VEC3; - case 4: return SH_BOOL_VEC4; - default: UNREACHABLE(); - } - } else { - return SH_BOOL; - } - case EbtSampler2D: return SH_SAMPLER_2D; - case EbtSamplerCube: return SH_SAMPLER_CUBE; - case EbtSamplerExternalOES: return SH_SAMPLER_EXTERNAL_OES; - case EbtSampler2DRect: return SH_SAMPLER_2D_RECT_ARB; - default: UNREACHABLE(); - } - return SH_NONE; -} - -void getBuiltInVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList); -void getUserDefinedVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList, - ShHashFunction64 hashFunction); +template +static void ExpandUserDefinedVariable(const VarT &variable, + const std::string &name, + const std::string &mappedName, + bool markStaticUse, + std::vector *expanded); // Returns info for an attribute, uniform, or varying. -void getVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList, - ShHashFunction64 hashFunction) +template +static void ExpandVariable(const VarT &variable, + const std::string &name, + const std::string &mappedName, + bool markStaticUse, + std::vector *expanded) { - if (type.getBasicType() == EbtStruct) { - if (type.isArray()) { - for (int i = 0; i < type.getArraySize(); ++i) { - TString lname = name + arrayBrackets(i); - TString lmappedName = mappedName + arrayBrackets(i); - getUserDefinedVariableInfo(type, lname, lmappedName, infoList, hashFunction); + if (variable.isStruct()) + { + if (variable.isArray()) + { + for (size_t elementIndex = 0; elementIndex < variable.elementCount(); elementIndex++) + { + std::string lname = name + ArrayString(elementIndex); + std::string lmappedName = mappedName + ArrayString(elementIndex); + ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded); } - } else { - getUserDefinedVariableInfo(type, name, mappedName, infoList, hashFunction); } - } else { - getBuiltInVariableInfo(type, name, mappedName, infoList); + else + { + ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded); + } } -} + else + { + VarT expandedVar = variable; -void getBuiltInVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList) -{ - ASSERT(type.getBasicType() != EbtStruct); - - TVariableInfo varInfo; - if (type.isArray()) { - varInfo.name = (name + "[0]").c_str(); - varInfo.mappedName = (mappedName + "[0]").c_str(); - varInfo.size = type.getArraySize(); - varInfo.isArray = true; - } else { - varInfo.name = name.c_str(); - varInfo.mappedName = mappedName.c_str(); - varInfo.size = 1; - varInfo.isArray = false; + expandedVar.name = name; + expandedVar.mappedName = mappedName; + + // Mark all expanded fields as used if the parent is used + if (markStaticUse) + { + expandedVar.staticUse = true; + } + + if (expandedVar.isArray()) + { + expandedVar.name += "[0]"; + expandedVar.mappedName += "[0]"; + } + + expanded->push_back(expandedVar); } - varInfo.precision = type.getPrecision(); - varInfo.type = getVariableDataType(type); - infoList.push_back(varInfo); } -void getUserDefinedVariableInfo(const TType& type, - const TString& name, - const TString& mappedName, - TVariableInfoList& infoList, - ShHashFunction64 hashFunction) +template +static void ExpandUserDefinedVariable(const VarT &variable, + const std::string &name, + const std::string &mappedName, + bool markStaticUse, + std::vector *expanded) { - ASSERT(type.getBasicType() == EbtStruct); - - const TFieldList& fields = type.getStruct()->fields(); - for (size_t i = 0; i < fields.size(); ++i) { - const TType& fieldType = *(fields[i]->type()); - const TString& fieldName = fields[i]->name(); - getVariableInfo(fieldType, - name + "." + fieldName, - mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction), - infoList, - hashFunction); + ASSERT(variable.isStruct()); + + const std::vector &fields = variable.fields; + + for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) + { + const VarT &field = fields[fieldIndex]; + ExpandVariable(field, + name + "." + field.name, + mappedName + "." + field.mappedName, + markStaticUse, + expanded); } } -TVariableInfo* findVariable(const TType& type, - const TString& name, - TVariableInfoList& infoList) +template +static VarT *FindVariable(const TString &name, + std::vector *infoList) { // TODO(zmo): optimize this function. - TString myName = name; - if (type.isArray()) - myName += "[0]"; - for (size_t ii = 0; ii < infoList.size(); ++ii) + for (size_t ii = 0; ii < infoList->size(); ++ii) { - if (infoList[ii].name.c_str() == myName) - return &(infoList[ii]); + if ((*infoList)[ii].name.c_str() == name) + return &((*infoList)[ii]); } - return NULL; -} - -} // namespace anonymous - -TVariableInfo::TVariableInfo() - : type(SH_NONE), - size(0), - isArray(false), - precision(EbpUndefined), - staticUse(false) -{ -} -TVariableInfo::TVariableInfo(ShDataType type, int size) - : type(type), - size(size), - isArray(false), - precision(EbpUndefined), - staticUse(false) -{ + return NULL; } -CollectVariables::CollectVariables(TVariableInfoList& attribs, - TVariableInfoList& uniforms, - TVariableInfoList& varyings, +CollectVariables::CollectVariables(std::vector *attribs, + std::vector *outputVariables, + std::vector *uniforms, + std::vector *varyings, + std::vector *interfaceBlocks, ShHashFunction64 hashFunction) : mAttribs(attribs), + mOutputVariables(outputVariables), mUniforms(uniforms), mVaryings(varyings), + mInterfaceBlocks(interfaceBlocks), mPointCoordAdded(false), mFrontFacingAdded(false), mFragCoordAdded(false), @@ -203,110 +122,254 @@ CollectVariables::CollectVariables(TVariableInfoList& attribs, // Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count // toward varying counting if they are statically used in a fragment // shader. -void CollectVariables::visitSymbol(TIntermSymbol* symbol) +void CollectVariables::visitSymbol(TIntermSymbol *symbol) { ASSERT(symbol != NULL); - TVariableInfo* var = NULL; - switch (symbol->getQualifier()) + sh::ShaderVariable *var = NULL; + const TString &symbolName = symbol->getSymbol(); + + if (sh::IsVarying(symbol->getQualifier())) { - case EvqVaryingOut: - case EvqInvariantVaryingOut: - case EvqVaryingIn: - case EvqInvariantVaryingIn: - var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings); - break; - case EvqUniform: - var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms); - break; - case EvqFragCoord: - if (!mFragCoordAdded) { - TVariableInfo info; - info.name = "gl_FragCoord"; - info.mappedName = "gl_FragCoord"; - info.type = SH_FLOAT_VEC4; - info.size = 1; - info.precision = EbpMedium; // Use mediump as it doesn't really matter. - info.staticUse = true; - mVaryings.push_back(info); - mFragCoordAdded = true; - } - return; - case EvqFrontFacing: - if (!mFrontFacingAdded) { - TVariableInfo info; - info.name = "gl_FrontFacing"; - info.mappedName = "gl_FrontFacing"; - info.type = SH_BOOL; - info.size = 1; - info.precision = EbpUndefined; - info.staticUse = true; - mVaryings.push_back(info); - mFrontFacingAdded = true; - } - return; - case EvqPointCoord: - if (!mPointCoordAdded) { - TVariableInfo info; - info.name = "gl_PointCoord"; - info.mappedName = "gl_PointCoord"; - info.type = SH_FLOAT_VEC2; - info.size = 1; - info.precision = EbpMedium; // Use mediump as it doesn't really matter. - info.staticUse = true; - mVaryings.push_back(info); - mPointCoordAdded = true; + var = FindVariable(symbolName, mVaryings); + } + else if (symbol->getType() != EbtInterfaceBlock) + { + switch (symbol->getQualifier()) + { + case EvqAttribute: + case EvqVertexIn: + var = FindVariable(symbolName, mAttribs); + break; + case EvqFragmentOut: + var = FindVariable(symbolName, mOutputVariables); + break; + case EvqUniform: + { + const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock(); + if (interfaceBlock) + { + sh::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 + { + var = FindVariable(symbolName, mUniforms); + } + + // It's an internal error to reference an undefined user uniform + ASSERT(symbolName.compare(0, 3, "gl_") == 0 || var); + } + break; + case EvqFragCoord: + if (!mFragCoordAdded) + { + sh::Varying info; + info.name = "gl_FragCoord"; + info.mappedName = "gl_FragCoord"; + info.type = GL_FLOAT_VEC4; + info.arraySize = 0; + info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter. + info.staticUse = true; + mVaryings->push_back(info); + mFragCoordAdded = true; + } + return; + case EvqFrontFacing: + if (!mFrontFacingAdded) + { + sh::Varying info; + info.name = "gl_FrontFacing"; + info.mappedName = "gl_FrontFacing"; + info.type = GL_BOOL; + info.arraySize = 0; + info.precision = GL_NONE; + info.staticUse = true; + mVaryings->push_back(info); + mFrontFacingAdded = true; + } + return; + case EvqPointCoord: + if (!mPointCoordAdded) + { + sh::Varying info; + info.name = "gl_PointCoord"; + info.mappedName = "gl_PointCoord"; + info.type = GL_FLOAT_VEC2; + info.arraySize = 0; + info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter. + info.staticUse = true; + mVaryings->push_back(info); + mPointCoordAdded = true; + } + return; + default: + break; } - return; - default: - break; } if (var) + { var->staticUse = true; + } +} + +template +class NameHashingTraverser : public sh::GetVariableTraverser +{ + public: + NameHashingTraverser(std::vector *output, ShHashFunction64 hashFunction) + : sh::GetVariableTraverser(output), + mHashFunction(hashFunction) + {} + + private: + void visitVariable(VarT *variable) + { + TString stringName = TString(variable->name.c_str()); + variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str(); + } + + ShHashFunction64 mHashFunction; +}; + +// Attributes, which cannot have struct fields, are a special case +template <> +void CollectVariables::visitVariable(const TIntermSymbol *variable, + std::vector *infoList) const +{ + ASSERT(variable); + const TType &type = variable->getType(); + ASSERT(!type.getStruct()); + + sh::Attribute attribute; + + attribute.type = sh::GLVariableType(type); + attribute.precision = sh::GLVariablePrecision(type); + attribute.name = variable->getSymbol().c_str(); + attribute.arraySize = static_cast(type.getArraySize()); + attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str(); + attribute.location = variable->getType().getLayoutQualifier().location; + + infoList->push_back(attribute); } -bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node) +template <> +void CollectVariables::visitVariable(const TIntermSymbol *variable, + std::vector *infoList) const +{ + sh::InterfaceBlock interfaceBlock; + const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock(); + + bool isRowMajor = (blockType->matrixPacking() == EmpRowMajor); + + interfaceBlock.name = blockType->name().c_str(); + interfaceBlock.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str(); + interfaceBlock.arraySize = variable->getArraySize(); + interfaceBlock.isRowMajorLayout = isRowMajor; + interfaceBlock.layout = sh::GetBlockLayoutType(blockType->blockStorage()); + + ASSERT(blockType); + const TFieldList &blockFields = blockType->fields(); + + for (size_t fieldIndex = 0; fieldIndex < blockFields.size(); fieldIndex++) + { + const TField *field = blockFields[fieldIndex]; + ASSERT(field); + + sh::GetInterfaceBlockFieldTraverser traverser(&interfaceBlock.fields, isRowMajor); + traverser.traverse(*field->type(), field->name()); + } + + infoList->push_back(interfaceBlock); +} + +template +void CollectVariables::visitVariable(const TIntermSymbol *variable, + std::vector *infoList) const +{ + NameHashingTraverser traverser(infoList, mHashFunction); + traverser.traverse(variable->getType(), variable->getSymbol()); +} + +template +void CollectVariables::visitInfoList(const TIntermSequence &sequence, + std::vector *infoList) const +{ + for (size_t seqIndex = 0; seqIndex < sequence.size(); seqIndex++) + { + const TIntermSymbol *variable = sequence[seqIndex]->getAsSymbolNode(); + // The only case in which the sequence will not contain a + // TIntermSymbol node is initialization. It will contain a + // TInterBinary node in that case. Since attributes, uniforms, + // and varyings cannot be initialized in a shader, we must have + // only TIntermSymbol nodes in the sequence. + ASSERT(variable != NULL); + visitVariable(variable, infoList); + } +} + +bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node) { bool visitChildren = true; switch (node->getOp()) { - case EOpDeclaration: { - const TIntermSequence& sequence = node->getSequence(); - TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier(); - if (qualifier == EvqAttribute || qualifier == EvqUniform || - qualifier == EvqVaryingIn || qualifier == EvqVaryingOut || - qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut) + case EOpDeclaration: { - TVariableInfoList& infoList = qualifier == EvqAttribute ? mAttribs : - (qualifier == EvqUniform ? mUniforms : mVaryings); - for (TIntermSequence::const_iterator i = sequence.begin(); - i != sequence.end(); ++i) + const TIntermSequence &sequence = *(node->getSequence()); + const TIntermTyped &typedNode = *(sequence.front()->getAsTyped()); + TQualifier qualifier = typedNode.getQualifier(); + + if (typedNode.getBasicType() == EbtInterfaceBlock) { - const TIntermSymbol* variable = (*i)->getAsSymbolNode(); - // The only case in which the sequence will not contain a - // TIntermSymbol node is initialization. It will contain a - // TInterBinary node in that case. Since attributes, uniforms, - // and varyings cannot be initialized in a shader, we must have - // only TIntermSymbol nodes in the sequence. - ASSERT(variable != NULL); - TString processedSymbol; - if (mHashFunction == NULL) - processedSymbol = variable->getSymbol(); - else - processedSymbol = TIntermTraverser::hash(variable->getOriginalSymbol(), mHashFunction); - getVariableInfo(variable->getType(), - variable->getOriginalSymbol(), - processedSymbol, - infoList, - mHashFunction); - visitChildren = false; + visitInfoList(sequence, mInterfaceBlocks); + } + else if (qualifier == EvqAttribute || qualifier == EvqVertexIn || + qualifier == EvqFragmentOut || qualifier == EvqUniform || + sh::IsVarying(qualifier)) + { + switch (qualifier) + { + case EvqAttribute: + case EvqVertexIn: + visitInfoList(sequence, mAttribs); + break; + case EvqFragmentOut: + visitInfoList(sequence, mOutputVariables); + break; + case EvqUniform: + visitInfoList(sequence, mUniforms); + break; + default: + visitInfoList(sequence, mVaryings); + break; + } + + if (!sequence.empty()) + { + visitChildren = false; + } } + break; } - break; - } - default: break; + default: break; } return visitChildren; } +template +void ExpandVariables(const std::vector &compact, std::vector *expanded) +{ + for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++) + { + const VarT &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 *); diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h index 37216cd142..3771819c8b 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h +++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h @@ -7,40 +7,37 @@ #ifndef COMPILER_VARIABLE_INFO_H_ #define COMPILER_VARIABLE_INFO_H_ -#include "GLSLANG/ShaderLang.h" #include "compiler/translator/intermediate.h" - -// Provides information about a variable. -// It is currently being used to store info about active attribs and uniforms. -struct TVariableInfo { - TVariableInfo(ShDataType type, int size); - TVariableInfo(); - - TPersistString name; - TPersistString mappedName; - ShDataType type; - int size; - bool isArray; - TPrecision precision; - bool staticUse; -}; -typedef std::vector TVariableInfoList; +#include "common/shadervars.h" // Traverses intermediate tree to collect all attributes, uniforms, varyings. -class CollectVariables : public TIntermTraverser { -public: - CollectVariables(TVariableInfoList& attribs, - TVariableInfoList& uniforms, - TVariableInfoList& varyings, +class CollectVariables : public TIntermTraverser +{ + public: + CollectVariables(std::vector *attribs, + std::vector *outputVariables, + std::vector *uniforms, + std::vector *varyings, + std::vector *interfaceBlocks, ShHashFunction64 hashFunction); - virtual void visitSymbol(TIntermSymbol*); - virtual bool visitAggregate(Visit, TIntermAggregate*); + virtual void visitSymbol(TIntermSymbol *symbol); + virtual bool visitAggregate(Visit, TIntermAggregate *node); + + private: + template + void visitVariable(const TIntermSymbol *variable, std::vector *infoList) const; -private: - TVariableInfoList& mAttribs; - TVariableInfoList& mUniforms; - TVariableInfoList& mVaryings; + 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::map mInterfaceBlockFields; bool mPointCoordAdded; bool mFrontFacingAdded; @@ -49,4 +46,9 @@ private: ShHashFunction64 mHashFunction; }; +// 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); + #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 5634d86337..faaf0115fc 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VariablePacker.cpp @@ -4,121 +4,78 @@ // found in the LICENSE file. // #include "compiler/translator/VariablePacker.h" +#include "angle_gl.h" +#include "common/utilities.h" #include -#include "compiler/translator/ShHandle.h" -namespace { -int GetSortOrder(ShDataType type) +int VariablePacker::GetNumComponentsPerRow(sh::GLenum type) { - switch (type) { - case SH_FLOAT_MAT4: - return 0; - case SH_FLOAT_MAT2: - return 1; - case SH_FLOAT_VEC4: - case SH_INT_VEC4: - case SH_BOOL_VEC4: - return 2; - case SH_FLOAT_MAT3: - return 3; - case SH_FLOAT_VEC3: - case SH_INT_VEC3: - case SH_BOOL_VEC3: - return 4; - case SH_FLOAT_VEC2: - case SH_INT_VEC2: - case SH_BOOL_VEC2: - return 5; - case SH_FLOAT: - case SH_INT: - case SH_BOOL: - case SH_SAMPLER_2D: - case SH_SAMPLER_CUBE: - case SH_SAMPLER_EXTERNAL_OES: - case SH_SAMPLER_2D_RECT_ARB: - return 6; - default: - ASSERT(false); - return 7; + switch (type) + { + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x2: + case GL_FLOAT_MAT4x3: + case GL_FLOAT_VEC4: + case GL_INT_VEC4: + case GL_BOOL_VEC4: + case GL_UNSIGNED_INT_VEC4: + return 4; + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT3x2: + case GL_FLOAT_VEC3: + case GL_INT_VEC3: + case GL_BOOL_VEC3: + case GL_UNSIGNED_INT_VEC3: + return 3; + case GL_FLOAT_VEC2: + case GL_INT_VEC2: + case GL_BOOL_VEC2: + case GL_UNSIGNED_INT_VEC2: + return 2; + default: + ASSERT(gl::VariableComponentCount(type) == 1); + return 1; } } -} // namespace -int VariablePacker::GetNumComponentsPerRow(ShDataType type) +int VariablePacker::GetNumRows(sh::GLenum type) { - switch (type) { - case SH_FLOAT_MAT4: - case SH_FLOAT_MAT2: - case SH_FLOAT_VEC4: - case SH_INT_VEC4: - case SH_BOOL_VEC4: - return 4; - case SH_FLOAT_MAT3: - case SH_FLOAT_VEC3: - case SH_INT_VEC3: - case SH_BOOL_VEC3: - return 3; - case SH_FLOAT_VEC2: - case SH_INT_VEC2: - case SH_BOOL_VEC2: - return 2; - case SH_FLOAT: - case SH_INT: - case SH_BOOL: - case SH_SAMPLER_2D: - case SH_SAMPLER_CUBE: - case SH_SAMPLER_EXTERNAL_OES: - case SH_SAMPLER_2D_RECT_ARB: - return 1; - default: - ASSERT(false); - return 5; + switch (type) + { + case GL_FLOAT_MAT4: + case GL_FLOAT_MAT2x4: + case GL_FLOAT_MAT3x4: + case GL_FLOAT_MAT4x3: + case GL_FLOAT_MAT4x2: + return 4; + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT2x3: + case GL_FLOAT_MAT3x2: + return 3; + case GL_FLOAT_MAT2: + return 2; + default: + ASSERT(gl::VariableRowCount(type) == 1); + return 1; } } -int VariablePacker::GetNumRows(ShDataType type) +struct TVariableInfoComparer { - switch (type) { - case SH_FLOAT_MAT4: - return 4; - case SH_FLOAT_MAT3: - return 3; - case SH_FLOAT_MAT2: - return 2; - case SH_FLOAT_VEC4: - case SH_INT_VEC4: - case SH_BOOL_VEC4: - case SH_FLOAT_VEC3: - case SH_INT_VEC3: - case SH_BOOL_VEC3: - case SH_FLOAT_VEC2: - case SH_INT_VEC2: - case SH_BOOL_VEC2: - case SH_FLOAT: - case SH_INT: - case SH_BOOL: - case SH_SAMPLER_2D: - case SH_SAMPLER_CUBE: - case SH_SAMPLER_EXTERNAL_OES: - case SH_SAMPLER_2D_RECT_ARB: - return 1; - default: - ASSERT(false); - return 100000; - } -} - -struct TVariableInfoComparer { - bool operator()(const TVariableInfo& lhs, const TVariableInfo& rhs) const + bool operator()(const sh::ShaderVariable &lhs, const sh::ShaderVariable &rhs) const { - int lhsSortOrder = GetSortOrder(lhs.type); - int rhsSortOrder = GetSortOrder(rhs.type); + int lhsSortOrder = gl::VariableSortOrder(lhs.type); + int rhsSortOrder = gl::VariableSortOrder(rhs.type); if (lhsSortOrder != rhsSortOrder) { return lhsSortOrder < rhsSortOrder; } // Sort by largest first. - return lhs.size > rhs.size; + return lhs.arraySize > rhs.arraySize; } }; @@ -189,13 +146,23 @@ bool VariablePacker::searchColumn(int column, int numRows, int* destRow, int* de return true; } -bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVariableInfoList& in_variables) +template +bool VariablePacker::CheckVariablesWithinPackingLimits(unsigned int maxVectors, + const std::vector &in_variables) { ASSERT(maxVectors > 0); maxRows_ = maxVectors; topNonFullRow_ = 0; bottomNonFullRow_ = maxRows_ - 1; - TVariableInfoList variables(in_variables); + std::vector variables(in_variables); + + // Check whether each variable fits in the available vectors. + for (size_t i = 0; i < variables.size(); i++) { + const sh::ShaderVariable &variable = variables[i]; + if (variable.elementCount() > maxVectors / GetNumRows(variable.type)) { + return false; + } + } // As per GLSL 1.017 Appendix A, Section 7 variables are packed in specific // order by type, then by size of array, largest first. @@ -206,11 +173,11 @@ bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVa // Packs the 4 column variables. size_t ii = 0; for (; ii < variables.size(); ++ii) { - const TVariableInfo& variable = variables[ii]; + const sh::ShaderVariable &variable = variables[ii]; if (GetNumComponentsPerRow(variable.type) != 4) { break; } - topNonFullRow_ += GetNumRows(variable.type) * variable.size; + topNonFullRow_ += GetNumRows(variable.type) * variable.elementCount(); } if (topNonFullRow_ > maxRows_) { @@ -220,11 +187,11 @@ bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVa // Packs the 3 column variables. int num3ColumnRows = 0; for (; ii < variables.size(); ++ii) { - const TVariableInfo& variable = variables[ii]; + const sh::ShaderVariable &variable = variables[ii]; if (GetNumComponentsPerRow(variable.type) != 3) { break; } - num3ColumnRows += GetNumRows(variable.type) * variable.size; + num3ColumnRows += GetNumRows(variable.type) * variable.elementCount(); } if (topNonFullRow_ + num3ColumnRows > maxRows_) { @@ -239,11 +206,11 @@ bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVa int rowsAvailableInColumns01 = twoColumnRowsAvailable; int rowsAvailableInColumns23 = twoColumnRowsAvailable; for (; ii < variables.size(); ++ii) { - const TVariableInfo& variable = variables[ii]; + const sh::ShaderVariable &variable = variables[ii]; if (GetNumComponentsPerRow(variable.type) != 2) { break; } - int numRows = GetNumRows(variable.type) * variable.size; + int numRows = GetNumRows(variable.type) * variable.elementCount(); if (numRows <= rowsAvailableInColumns01) { rowsAvailableInColumns01 -= numRows; } else if (numRows <= rowsAvailableInColumns23) { @@ -263,9 +230,9 @@ bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVa // Packs the 1 column variables. for (; ii < variables.size(); ++ii) { - const TVariableInfo& variable = variables[ii]; + const sh::ShaderVariable &variable = variables[ii]; ASSERT(1 == GetNumComponentsPerRow(variable.type)); - int numRows = GetNumRows(variable.type) * variable.size; + int numRows = GetNumRows(variable.type) * variable.elementCount(); int smallestColumn = -1; int smallestSize = maxRows_ + 1; int topRow = -1; @@ -293,5 +260,8 @@ bool VariablePacker::CheckVariablesWithinPackingLimits(int maxVectors, const TVa return true; } - - +// Instantiate all possible variable packings +template bool VariablePacker::CheckVariablesWithinPackingLimits(unsigned int, const std::vector &); +template bool VariablePacker::CheckVariablesWithinPackingLimits(unsigned int, const std::vector &); +template bool VariablePacker::CheckVariablesWithinPackingLimits(unsigned int, const std::vector &); +template bool VariablePacker::CheckVariablesWithinPackingLimits(unsigned int, const std::vector &); diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h index fd6090827c..1de5332d8a 100644 --- a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h +++ b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h @@ -8,23 +8,23 @@ #define _VARIABLEPACKER_INCLUDED_ #include -#include "compiler/translator/ShHandle.h" +#include "compiler/translator/VariableInfo.h" class VariablePacker { public: // Returns true if the passed in variables pack in maxVectors following // the packing rules from the GLSL 1.017 spec, Appendix A, section 7. - bool CheckVariablesWithinPackingLimits( - int maxVectors, - const TVariableInfoList& in_variables); + template + bool CheckVariablesWithinPackingLimits(unsigned int maxVectors, + const std::vector &in_variables); // Gets how many components in a row a data type takes. - static int GetNumComponentsPerRow(ShDataType type); + static int GetNumComponentsPerRow(sh::GLenum type); // Gets how many rows a data type takes. - static int GetNumRows(ShDataType type); + static int GetNumRows(sh::GLenum type); - private: + private: static const int kNumColumns = 4; static const unsigned kColumnMask = (1 << kNumColumns) - 1; diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp index dd11f99eb8..12dc9e0dad 100644 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp @@ -35,104 +35,81 @@ static const int GLSL_VERSION_120 = 120; // - invariant gl_Position; // - varying vec3 color; invariant color; // -TVersionGLSL::TVersionGLSL(ShShaderType type) - : mShaderType(type), - mVersion(GLSL_VERSION_110) +TVersionGLSL::TVersionGLSL(sh::GLenum type) + : mVersion(GLSL_VERSION_110) { } -void TVersionGLSL::visitSymbol(TIntermSymbol* node) +void TVersionGLSL::visitSymbol(TIntermSymbol *node) { if (node->getSymbol() == "gl_PointCoord") updateVersion(GLSL_VERSION_120); } -void TVersionGLSL::visitConstantUnion(TIntermConstantUnion*) -{ -} - -bool TVersionGLSL::visitBinary(Visit, TIntermBinary*) -{ - return true; -} - -bool TVersionGLSL::visitUnary(Visit, TIntermUnary*) -{ - return true; -} - -bool TVersionGLSL::visitSelection(Visit, TIntermSelection*) -{ - return true; -} - -bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate* node) +bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node) { bool visitChildren = true; - switch (node->getOp()) { + switch (node->getOp()) + { case EOpSequence: // We need to visit sequence children to get to global or inner scope. visitChildren = true; break; - case EOpDeclaration: { - const TIntermSequence& sequence = node->getSequence(); - TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier(); - if ((qualifier == EvqInvariantVaryingIn) || - (qualifier == EvqInvariantVaryingOut)) { - updateVersion(GLSL_VERSION_120); + case EOpDeclaration: + { + const TIntermSequence &sequence = *(node->getSequence()); + TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier(); + if ((qualifier == EvqInvariantVaryingIn) || + (qualifier == EvqInvariantVaryingOut)) + { + updateVersion(GLSL_VERSION_120); + } + break; } - break; - } - case EOpParameters: { - const TIntermSequence& params = node->getSequence(); - for (TIntermSequence::const_iterator iter = params.begin(); - iter != params.end(); ++iter) + case EOpParameters: { - const TIntermTyped* param = (*iter)->getAsTyped(); - if (param->isArray()) + const TIntermSequence ¶ms = *(node->getSequence()); + for (TIntermSequence::const_iterator iter = params.begin(); + iter != params.end(); ++iter) { - TQualifier qualifier = param->getQualifier(); - if ((qualifier == EvqOut) || (qualifier == EvqInOut)) + const TIntermTyped *param = (*iter)->getAsTyped(); + if (param->isArray()) { - updateVersion(GLSL_VERSION_120); - break; + TQualifier qualifier = param->getQualifier(); + if ((qualifier == EvqOut) || (qualifier == EvqInOut)) + { + updateVersion(GLSL_VERSION_120); + break; + } } } + // Fully processed. No need to visit children. + visitChildren = false; + break; } - // Fully processed. No need to visit children. - visitChildren = false; - break; - } case EOpConstructMat2: case EOpConstructMat3: - case EOpConstructMat4: { - const TIntermSequence& sequence = node->getSequence(); - if (sequence.size() == 1) { - TIntermTyped* typed = sequence.front()->getAsTyped(); - if (typed && typed->isMatrix()) { - updateVersion(GLSL_VERSION_120); - } + case EOpConstructMat4: + { + const TIntermSequence &sequence = *(node->getSequence()); + if (sequence.size() == 1) + { + TIntermTyped *typed = sequence.front()->getAsTyped(); + if (typed && typed->isMatrix()) + { + updateVersion(GLSL_VERSION_120); + } + } + break; } + default: break; - } - - default: break; } return visitChildren; } -bool TVersionGLSL::visitLoop(Visit, TIntermLoop*) -{ - return true; -} - -bool TVersionGLSL::visitBranch(Visit, TIntermBranch*) -{ - return true; -} - void TVersionGLSL::updateVersion(int version) { mVersion = std::max(version, mVersion); diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h index d310066171..de4141d38c 100644 --- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h +++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h @@ -1,13 +1,12 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // -#ifndef COMPILER_VERSIONGLSL_H_ -#define COMPILER_VERSIONGLSL_H_ +#ifndef COMPILER_TRANSLATOR_VERSIONGLSL_H_ +#define COMPILER_TRANSLATOR_VERSIONGLSL_H_ -#include "GLSLANG/ShaderLang.h" #include "compiler/translator/intermediate.h" // Traverses the intermediate tree to return the minimum GLSL version @@ -24,9 +23,11 @@ // - matrix constructors taking matrix as argument. // - array as "out" function parameters // -class TVersionGLSL : public TIntermTraverser { -public: - TVersionGLSL(ShShaderType type); +// TODO: ES3 equivalent versions of GLSL +class TVersionGLSL : public TIntermTraverser +{ + public: + TVersionGLSL(sh::GLenum type); // Returns 120 if the following is used the shader: // - "invariant", @@ -36,21 +37,14 @@ public: // Else 110 is returned. int getVersion() { return mVersion; } - virtual void visitSymbol(TIntermSymbol*); - virtual void visitConstantUnion(TIntermConstantUnion*); - virtual bool visitBinary(Visit, TIntermBinary*); - virtual bool visitUnary(Visit, TIntermUnary*); - virtual bool visitSelection(Visit, TIntermSelection*); - virtual bool visitAggregate(Visit, TIntermAggregate*); - virtual bool visitLoop(Visit, TIntermLoop*); - virtual bool visitBranch(Visit, TIntermBranch*); + virtual void visitSymbol(TIntermSymbol *); + virtual bool visitAggregate(Visit, TIntermAggregate *); -protected: + protected: void updateVersion(int version); -private: - ShShaderType mShaderType; + private: int mVersion; }; -#endif // COMPILER_VERSIONGLSL_H_ +#endif // COMPILER_TRANSLATOR_VERSIONGLSL_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp index d5f2cba5fc..1aeb822d51 100644 --- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.cpp @@ -6,24 +6,32 @@ #include "compiler/translator/depgraph/DependencyGraphBuilder.h" -void TDependencyGraphBuilder::build(TIntermNode* node, TDependencyGraph* graph) +void TDependencyGraphBuilder::build(TIntermNode *node, TDependencyGraph *graph) { TDependencyGraphBuilder builder(graph); builder.build(node); } -bool TDependencyGraphBuilder::visitAggregate(Visit visit, TIntermAggregate* intermAggregate) +bool TDependencyGraphBuilder::visitAggregate( + Visit visit, TIntermAggregate *intermAggregate) { - switch (intermAggregate->getOp()) { - case EOpFunction: visitFunctionDefinition(intermAggregate); break; - case EOpFunctionCall: visitFunctionCall(intermAggregate); break; - default: visitAggregateChildren(intermAggregate); break; + switch (intermAggregate->getOp()) + { + case EOpFunction: + visitFunctionDefinition(intermAggregate); + break; + case EOpFunctionCall: + visitFunctionCall(intermAggregate); + break; + default: + visitAggregateChildren(intermAggregate); + break; } - return false; } -void TDependencyGraphBuilder::visitFunctionDefinition(TIntermAggregate* intermAggregate) +void TDependencyGraphBuilder::visitFunctionDefinition( + TIntermAggregate *intermAggregate) { // Currently, we do not support user defined functions. if (intermAggregate->getName() != "main(") @@ -34,64 +42,71 @@ void TDependencyGraphBuilder::visitFunctionDefinition(TIntermAggregate* intermAg // Takes an expression like "f(x)" and creates a dependency graph like // "x -> argument 0 -> function call". -void TDependencyGraphBuilder::visitFunctionCall(TIntermAggregate* intermFunctionCall) +void TDependencyGraphBuilder::visitFunctionCall( + TIntermAggregate *intermFunctionCall) { - TGraphFunctionCall* functionCall = mGraph->createFunctionCall(intermFunctionCall); + TGraphFunctionCall *functionCall = + mGraph->createFunctionCall(intermFunctionCall); // Run through the function call arguments. int argumentNumber = 0; - TIntermSequence& intermArguments = intermFunctionCall->getSequence(); - for (TIntermSequence::const_iterator iter = intermArguments.begin(); - iter != intermArguments.end(); + TIntermSequence *intermArguments = intermFunctionCall->getSequence(); + for (TIntermSequence::const_iterator iter = intermArguments->begin(); + iter != intermArguments->end(); ++iter, ++argumentNumber) { TNodeSetMaintainer nodeSetMaintainer(this); - TIntermNode* intermArgument = *iter; + TIntermNode *intermArgument = *iter; intermArgument->traverse(this); - if (TParentNodeSet* argumentNodes = mNodeSets.getTopSet()) { - TGraphArgument* argument = mGraph->createArgument(intermFunctionCall, argumentNumber); + if (TParentNodeSet *argumentNodes = mNodeSets.getTopSet()) + { + TGraphArgument *argument = mGraph->createArgument( + intermFunctionCall, argumentNumber); connectMultipleNodesToSingleNode(argumentNodes, argument); argument->addDependentNode(functionCall); } } - // Push the leftmost symbol of this function call into the current set of dependent symbols to - // represent the result of this function call. + // Push the leftmost symbol of this function call into the current set of + // dependent symbols to represent the result of this function call. // Thus, an expression like "y = f(x)" will yield a dependency graph like // "x -> argument 0 -> function call -> y". - // This line essentially passes the function call node back up to an earlier visitAssignment - // call, which will create the connection "function call -> y". + // This line essentially passes the function call node back up to an earlier + // visitAssignment call, which will create the connection "function call -> y". mNodeSets.insertIntoTopSet(functionCall); } -void TDependencyGraphBuilder::visitAggregateChildren(TIntermAggregate* intermAggregate) +void TDependencyGraphBuilder::visitAggregateChildren( + TIntermAggregate *intermAggregate) { - TIntermSequence& sequence = intermAggregate->getSequence(); - for(TIntermSequence::const_iterator iter = sequence.begin(); iter != sequence.end(); ++iter) + TIntermSequence *sequence = intermAggregate->getSequence(); + for (TIntermSequence::const_iterator iter = sequence->begin(); + iter != sequence->end(); ++iter) { - TIntermNode* intermChild = *iter; + TIntermNode *intermChild = *iter; intermChild->traverse(this); } } -void TDependencyGraphBuilder::visitSymbol(TIntermSymbol* intermSymbol) +void TDependencyGraphBuilder::visitSymbol(TIntermSymbol *intermSymbol) { - // Push this symbol into the set of dependent symbols for the current assignment or condition - // that we are traversing. - TGraphSymbol* symbol = mGraph->getOrCreateSymbol(intermSymbol); + // Push this symbol into the set of dependent symbols for the current + // assignment or condition that we are traversing. + TGraphSymbol *symbol = mGraph->getOrCreateSymbol(intermSymbol); mNodeSets.insertIntoTopSet(symbol); - // If this symbol is the current leftmost symbol under an assignment, replace the previous - // leftmost symbol with this symbol. - if (!mLeftmostSymbols.empty() && mLeftmostSymbols.top() != &mRightSubtree) { + // If this symbol is the current leftmost symbol under an assignment, replace + // the previous leftmost symbol with this symbol. + if (!mLeftmostSymbols.empty() && mLeftmostSymbols.top() != &mRightSubtree) + { mLeftmostSymbols.pop(); mLeftmostSymbols.push(symbol); } } -bool TDependencyGraphBuilder::visitBinary(Visit visit, TIntermBinary* intermBinary) +bool TDependencyGraphBuilder::visitBinary(Visit visit, TIntermBinary *intermBinary) { TOperator op = intermBinary->getOp(); if (op == EOpInitialize || intermBinary->isAssignment()) @@ -104,13 +119,13 @@ bool TDependencyGraphBuilder::visitBinary(Visit visit, TIntermBinary* intermBina return false; } -void TDependencyGraphBuilder::visitAssignment(TIntermBinary* intermAssignment) +void TDependencyGraphBuilder::visitAssignment(TIntermBinary *intermAssignment) { - TIntermTyped* intermLeft = intermAssignment->getLeft(); + TIntermTyped *intermLeft = intermAssignment->getLeft(); if (!intermLeft) return; - TGraphSymbol* leftmostSymbol = NULL; + TGraphSymbol *leftmostSymbol = NULL; { TNodeSetMaintainer nodeSetMaintainer(this); @@ -120,88 +135,100 @@ void TDependencyGraphBuilder::visitAssignment(TIntermBinary* intermAssignment) intermLeft->traverse(this); leftmostSymbol = mLeftmostSymbols.top(); - // After traversing the left subtree of this assignment, we should have found a real - // leftmost symbol, and the leftmost symbol should not be a placeholder. + // After traversing the left subtree of this assignment, we should + // have found a real leftmost symbol, and the leftmost symbol should + // not be a placeholder. ASSERT(leftmostSymbol != &mLeftSubtree); ASSERT(leftmostSymbol != &mRightSubtree); } - if (TIntermTyped* intermRight = intermAssignment->getRight()) { + if (TIntermTyped *intermRight = intermAssignment->getRight()) + { TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree); intermRight->traverse(this); } - if (TParentNodeSet* assignmentNodes = mNodeSets.getTopSet()) + if (TParentNodeSet *assignmentNodes = mNodeSets.getTopSet()) connectMultipleNodesToSingleNode(assignmentNodes, leftmostSymbol); } - // Push the leftmost symbol of this assignment into the current set of dependent symbols to - // represent the result of this assignment. - // An expression like "a = (b = c)" will yield a dependency graph like "c -> b -> a". - // This line essentially passes the leftmost symbol of the nested assignment ("b" in this - // example) back up to the earlier visitAssignment call for the outer assignment, which will - // create the connection "b -> a". + // Push the leftmost symbol of this assignment into the current set of dependent + // symbols to represent the result of this assignment. + // An expression like "a = (b = c)" will yield a dependency graph like + // "c -> b -> a". + // This line essentially passes the leftmost symbol of the nested assignment + // ("b" in this example) back up to the earlier visitAssignment call for the + // outer assignment, which will create the connection "b -> a". mNodeSets.insertIntoTopSet(leftmostSymbol); } -void TDependencyGraphBuilder::visitLogicalOp(TIntermBinary* intermLogicalOp) +void TDependencyGraphBuilder::visitLogicalOp(TIntermBinary *intermLogicalOp) { - if (TIntermTyped* intermLeft = intermLogicalOp->getLeft()) { + if (TIntermTyped *intermLeft = intermLogicalOp->getLeft()) + { TNodeSetPropagatingMaintainer nodeSetMaintainer(this); intermLeft->traverse(this); - if (TParentNodeSet* leftNodes = mNodeSets.getTopSet()) { - TGraphLogicalOp* logicalOp = mGraph->createLogicalOp(intermLogicalOp); + if (TParentNodeSet *leftNodes = mNodeSets.getTopSet()) + { + TGraphLogicalOp *logicalOp = mGraph->createLogicalOp(intermLogicalOp); connectMultipleNodesToSingleNode(leftNodes, logicalOp); } } - if (TIntermTyped* intermRight = intermLogicalOp->getRight()) { + if (TIntermTyped *intermRight = intermLogicalOp->getRight()) + { TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree); intermRight->traverse(this); } } -void TDependencyGraphBuilder::visitBinaryChildren(TIntermBinary* intermBinary) +void TDependencyGraphBuilder::visitBinaryChildren(TIntermBinary *intermBinary) { - if (TIntermTyped* intermLeft = intermBinary->getLeft()) + if (TIntermTyped *intermLeft = intermBinary->getLeft()) intermLeft->traverse(this); - if (TIntermTyped* intermRight = intermBinary->getRight()) { + if (TIntermTyped *intermRight = intermBinary->getRight()) + { TLeftmostSymbolMaintainer leftmostSymbolMaintainer(this, mRightSubtree); intermRight->traverse(this); } } -bool TDependencyGraphBuilder::visitSelection(Visit visit, TIntermSelection* intermSelection) +bool TDependencyGraphBuilder::visitSelection( + Visit visit, TIntermSelection *intermSelection) { - if (TIntermNode* intermCondition = intermSelection->getCondition()) { + if (TIntermNode *intermCondition = intermSelection->getCondition()) + { TNodeSetMaintainer nodeSetMaintainer(this); intermCondition->traverse(this); - if (TParentNodeSet* conditionNodes = mNodeSets.getTopSet()) { - TGraphSelection* selection = mGraph->createSelection(intermSelection); + if (TParentNodeSet *conditionNodes = mNodeSets.getTopSet()) + { + TGraphSelection *selection = mGraph->createSelection(intermSelection); connectMultipleNodesToSingleNode(conditionNodes, selection); } } - if (TIntermNode* intermTrueBlock = intermSelection->getTrueBlock()) + if (TIntermNode *intermTrueBlock = intermSelection->getTrueBlock()) intermTrueBlock->traverse(this); - if (TIntermNode* intermFalseBlock = intermSelection->getFalseBlock()) + if (TIntermNode *intermFalseBlock = intermSelection->getFalseBlock()) intermFalseBlock->traverse(this); return false; } -bool TDependencyGraphBuilder::visitLoop(Visit visit, TIntermLoop* intermLoop) +bool TDependencyGraphBuilder::visitLoop(Visit visit, TIntermLoop *intermLoop) { - if (TIntermTyped* intermCondition = intermLoop->getCondition()) { + if (TIntermTyped *intermCondition = intermLoop->getCondition()) + { TNodeSetMaintainer nodeSetMaintainer(this); intermCondition->traverse(this); - if (TParentNodeSet* conditionNodes = mNodeSets.getTopSet()) { - TGraphLoop* loop = mGraph->createLoop(intermLoop); + if (TParentNodeSet *conditionNodes = mNodeSets.getTopSet()) + { + TGraphLoop *loop = mGraph->createLoop(intermLoop); connectMultipleNodesToSingleNode(conditionNodes, loop); } } @@ -209,19 +236,20 @@ bool TDependencyGraphBuilder::visitLoop(Visit visit, TIntermLoop* intermLoop) if (TIntermNode* intermBody = intermLoop->getBody()) intermBody->traverse(this); - if (TIntermTyped* intermExpression = intermLoop->getExpression()) + if (TIntermTyped *intermExpression = intermLoop->getExpression()) intermExpression->traverse(this); return false; } -void TDependencyGraphBuilder::connectMultipleNodesToSingleNode(TParentNodeSet* nodes, - TGraphNode* node) const +void TDependencyGraphBuilder::connectMultipleNodesToSingleNode( + TParentNodeSet *nodes, TGraphNode *node) const { - for (TParentNodeSet::const_iterator iter = nodes->begin(); iter != nodes->end(); ++iter) + for (TParentNodeSet::const_iterator iter = nodes->begin(); + iter != nodes->end(); ++iter) { - TGraphParentNode* currentNode = *iter; + TGraphParentNode *currentNode = *iter; currentNode->addDependentNode(node); } } diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h index 3e928fb77e..b76f075e68 100644 --- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h +++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h @@ -4,55 +4,58 @@ // found in the LICENSE file. // -#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H -#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H +#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H +#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H #include "compiler/translator/depgraph/DependencyGraph.h" // -// Creates a dependency graph of symbols, function calls, conditions etc. by traversing a -// intermediate tree. +// Creates a dependency graph of symbols, function calls, conditions etc. by +// traversing a intermediate tree. // -class TDependencyGraphBuilder : public TIntermTraverser { -public: - static void build(TIntermNode* node, TDependencyGraph* graph); +class TDependencyGraphBuilder : public TIntermTraverser +{ + public: + static void build(TIntermNode *node, TDependencyGraph *graph); - virtual void visitSymbol(TIntermSymbol*); - virtual bool visitBinary(Visit visit, TIntermBinary*); - virtual bool visitSelection(Visit visit, TIntermSelection*); - virtual bool visitAggregate(Visit visit, TIntermAggregate*); - virtual bool visitLoop(Visit visit, TIntermLoop*); + virtual void visitSymbol(TIntermSymbol *); + virtual bool visitBinary(Visit visit, TIntermBinary *); + virtual bool visitSelection(Visit visit, TIntermSelection *); + virtual bool visitAggregate(Visit visit, TIntermAggregate *); + virtual bool visitLoop(Visit visit, TIntermLoop *); -private: - typedef std::stack TSymbolStack; - typedef std::set TParentNodeSet; + private: + typedef std::stack TSymbolStack; + typedef std::set TParentNodeSet; // // For collecting the dependent nodes of assignments, conditions, etc. // while traversing the intermediate tree. // - // This data structure is stack of sets. Each set contains dependency graph parent nodes. + // This data structure is stack of sets. Each set contains dependency graph + // parent nodes. // - class TNodeSetStack { - public: + class TNodeSetStack + { + public: TNodeSetStack() {}; ~TNodeSetStack() { clear(); } // This should only be called after a pushSet. // Returns NULL if the top set is empty. - TParentNodeSet* getTopSet() const + TParentNodeSet *getTopSet() const { - ASSERT(!nodeSets.empty()); - TParentNodeSet* topSet = nodeSets.top(); + ASSERT(!mNodeSets.empty()); + TParentNodeSet *topSet = mNodeSets.top(); return !topSet->empty() ? topSet : NULL; } - void pushSet() { nodeSets.push(new TParentNodeSet()); } + void pushSet() { mNodeSets.push(new TParentNodeSet()); } void popSet() { - ASSERT(!nodeSets.empty()); - delete nodeSets.top(); - nodeSets.pop(); + ASSERT(!mNodeSets.empty()); + delete mNodeSets.top(); + mNodeSets.pop(); } // Pops the top set and adds its contents to the new top set. @@ -60,12 +63,13 @@ private: // If there is no set below the top set, the top set is just deleted. void popSetIntoNext() { - ASSERT(!nodeSets.empty()); - TParentNodeSet* oldTopSet = nodeSets.top(); - nodeSets.pop(); + ASSERT(!mNodeSets.empty()); + TParentNodeSet *oldTopSet = mNodeSets.top(); + mNodeSets.pop(); - if (!nodeSets.empty()) { - TParentNodeSet* newTopSet = nodeSets.top(); + if (!mNodeSets.empty()) + { + TParentNodeSet *newTopSet = mNodeSets.top(); newTopSet->insert(oldTopSet->begin(), oldTopSet->end()); } @@ -76,106 +80,120 @@ private: // This can be called when there is no top set if we are visiting // symbols that are not under an assignment or condition. // We don't need to track those symbols. - void insertIntoTopSet(TGraphParentNode* node) + void insertIntoTopSet(TGraphParentNode *node) { - if (nodeSets.empty()) + if (mNodeSets.empty()) return; - nodeSets.top()->insert(node); + mNodeSets.top()->insert(node); } void clear() { - while (!nodeSets.empty()) + while (!mNodeSets.empty()) popSet(); } - private: - typedef std::stack TParentNodeSetStack; + private: + typedef std::stack TParentNodeSetStack; - TParentNodeSetStack nodeSets; + TParentNodeSetStack mNodeSets; }; // // An instance of this class pushes a new node set when instantiated. // When the instance goes out of scope, it and pops the node set. // - class TNodeSetMaintainer { - public: - TNodeSetMaintainer(TDependencyGraphBuilder* factory) - : sets(factory->mNodeSets) { sets.pushSet(); } - ~TNodeSetMaintainer() { sets.popSet(); } - protected: - TNodeSetStack& sets; + class TNodeSetMaintainer + { + public: + TNodeSetMaintainer(TDependencyGraphBuilder *factory) + : mSets(factory->mNodeSets) + { + mSets.pushSet(); + } + ~TNodeSetMaintainer() { mSets.popSet(); } + protected: + TNodeSetStack &mSets; }; // // An instance of this class pushes a new node set when instantiated. - // When the instance goes out of scope, it and pops the top node set and adds its contents to - // the new top node set. + // When the instance goes out of scope, it and pops the top node set and adds + // its contents to the new top node set. // - class TNodeSetPropagatingMaintainer { - public: - TNodeSetPropagatingMaintainer(TDependencyGraphBuilder* factory) - : sets(factory->mNodeSets) { sets.pushSet(); } - ~TNodeSetPropagatingMaintainer() { sets.popSetIntoNext(); } - protected: - TNodeSetStack& sets; + class TNodeSetPropagatingMaintainer + { + public: + TNodeSetPropagatingMaintainer(TDependencyGraphBuilder *factory) + : mSets(factory->mNodeSets) + { + mSets.pushSet(); + } + ~TNodeSetPropagatingMaintainer() { mSets.popSetIntoNext(); } + protected: + TNodeSetStack &mSets; }; // - // An instance of this class keeps track of the leftmost symbol while we're exploring an - // assignment. - // It will push the placeholder symbol kLeftSubtree when instantiated under a left subtree, - // and kRightSubtree under a right subtree. - // When it goes out of scope, it will pop the leftmost symbol at the top of the scope. - // During traversal, the TDependencyGraphBuilder will replace kLeftSubtree with a real symbol. - // kRightSubtree will never be replaced by a real symbol because we are tracking the leftmost - // symbol. + // An instance of this class keeps track of the leftmost symbol while we're + // exploring an assignment. + // It will push the placeholder symbol kLeftSubtree when instantiated under a + // left subtree, and kRightSubtree under a right subtree. + // When it goes out of scope, it will pop the leftmost symbol at the top of the + // scope. + // During traversal, the TDependencyGraphBuilder will replace kLeftSubtree with + // a real symbol. + // kRightSubtree will never be replaced by a real symbol because we are tracking + // the leftmost symbol. // - class TLeftmostSymbolMaintainer { - public: - TLeftmostSymbolMaintainer(TDependencyGraphBuilder* factory, TGraphSymbol& subtree) - : leftmostSymbols(factory->mLeftmostSymbols) + class TLeftmostSymbolMaintainer + { + public: + TLeftmostSymbolMaintainer( + TDependencyGraphBuilder *factory, TGraphSymbol &subtree) + : mLeftmostSymbols(factory->mLeftmostSymbols) { - needsPlaceholderSymbol = leftmostSymbols.empty() || leftmostSymbols.top() != &subtree; - if (needsPlaceholderSymbol) - leftmostSymbols.push(&subtree); + mNeedsPlaceholderSymbol = + mLeftmostSymbols.empty() || mLeftmostSymbols.top() != &subtree; + if (mNeedsPlaceholderSymbol) + mLeftmostSymbols.push(&subtree); } ~TLeftmostSymbolMaintainer() { - if (needsPlaceholderSymbol) - leftmostSymbols.pop(); + if (mNeedsPlaceholderSymbol) + mLeftmostSymbols.pop(); } - protected: - TSymbolStack& leftmostSymbols; - bool needsPlaceholderSymbol; + protected: + TSymbolStack& mLeftmostSymbols; + bool mNeedsPlaceholderSymbol; }; - TDependencyGraphBuilder(TDependencyGraph* graph) - : TIntermTraverser(true, false, false) - , mLeftSubtree(NULL) - , mRightSubtree(NULL) - , mGraph(graph) {} - void build(TIntermNode* intermNode) { intermNode->traverse(this); } + TDependencyGraphBuilder(TDependencyGraph *graph) + : TIntermTraverser(true, false, false), + mLeftSubtree(NULL), + mRightSubtree(NULL), + mGraph(graph) {} + void build(TIntermNode *intermNode) { intermNode->traverse(this); } - void connectMultipleNodesToSingleNode(TParentNodeSet* nodes, TGraphNode* node) const; + void connectMultipleNodesToSingleNode( + TParentNodeSet *nodes, TGraphNode *node) const; - void visitAssignment(TIntermBinary*); - void visitLogicalOp(TIntermBinary*); - void visitBinaryChildren(TIntermBinary*); - void visitFunctionDefinition(TIntermAggregate*); - void visitFunctionCall(TIntermAggregate* intermFunctionCall); - void visitAggregateChildren(TIntermAggregate*); + void visitAssignment(TIntermBinary *); + void visitLogicalOp(TIntermBinary *); + void visitBinaryChildren(TIntermBinary *); + void visitFunctionDefinition(TIntermAggregate *); + void visitFunctionCall(TIntermAggregate *intermFunctionCall); + void visitAggregateChildren(TIntermAggregate *); TGraphSymbol mLeftSubtree; TGraphSymbol mRightSubtree; - TDependencyGraph* mGraph; + TDependencyGraph *mGraph; TNodeSetStack mNodeSets; TSymbolStack mLeftmostSymbols; }; -#endif // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H +#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.l b/src/3rdparty/angle/src/compiler/translator/glslang.l index ffc1aa18ac..518b78df11 100644 --- a/src/3rdparty/angle/src/compiler/translator/glslang.l +++ b/src/3rdparty/angle/src/compiler/translator/glslang.l @@ -1,6 +1,6 @@ /* // -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -15,7 +15,7 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). %top{ // -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -40,6 +40,7 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). #include "compiler/translator/ParseContext.h" #include "compiler/preprocessor/Token.h" #include "compiler/translator/util.h" +#include "compiler/translator/length_limits.h" #include "glslang_tab.h" /* windows only pragma */ @@ -57,8 +58,13 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp). static yy_size_t string_input(char* buf, yy_size_t max_size, yyscan_t yyscanner); static int check_type(yyscan_t yyscanner); static int reserved_word(yyscan_t yyscanner); +static int ES2_reserved_ES3_keyword(TParseContext *context, int token); +static int ES2_keyword_ES3_reserved(TParseContext *context, int token); +static int ES2_ident_ES3_keyword(TParseContext *context, int token); +static int uint_constant(TParseContext *context); static int int_constant(yyscan_t yyscanner); static int float_constant(yyscan_t yyscanner); +static int floatsuffix_check(TParseContext* context); %} %option noyywrap nounput never-interactive @@ -73,16 +79,20 @@ O [0-7] %% +%{ + TParseContext* context = yyextra; +%} + "invariant" { return INVARIANT; } "highp" { return HIGH_PRECISION; } "mediump" { return MEDIUM_PRECISION; } "lowp" { return LOW_PRECISION; } "precision" { return PRECISION; } -"attribute" { return ATTRIBUTE; } +"attribute" { return ES2_keyword_ES3_reserved(context, ATTRIBUTE); } "const" { return CONST_QUAL; } "uniform" { return UNIFORM; } -"varying" { return VARYING; } +"varying" { return ES2_keyword_ES3_reserved(context, VARYING); } "break" { return BREAK; } "continue" { return CONTINUE; } @@ -92,6 +102,13 @@ O [0-7] "if" { return IF; } "else" { return ELSE; } +"switch" { return ES2_reserved_ES3_keyword(context, SWITCH); } +"case" { return ES2_ident_ES3_keyword(context, CASE); } +"default" { return ES2_reserved_ES3_keyword(context, DEFAULT); } + +"centroid" { return ES2_ident_ES3_keyword(context, CENTROID); } +"flat" { return ES2_reserved_ES3_keyword(context, FLAT); } +"smooth" { return ES2_ident_ES3_keyword(context, SMOOTH); } "in" { return IN_QUAL; } "out" { return OUT_QUAL; } @@ -99,6 +116,7 @@ O [0-7] "float" { return FLOAT_TYPE; } "int" { return INT_TYPE; } +"uint" { return ES2_ident_ES3_keyword(context, UINT_TYPE); } "void" { return VOID_TYPE; } "bool" { return BOOL_TYPE; } "true" { yylval->lex.b = true; return BOOLCONSTANT; } @@ -111,6 +129,17 @@ O [0-7] "mat3" { return MATRIX3; } "mat4" { return MATRIX4; } +"mat2x2" { return ES2_ident_ES3_keyword(context, MATRIX2); } +"mat3x3" { return ES2_ident_ES3_keyword(context, MATRIX3); } +"mat4x4" { return ES2_ident_ES3_keyword(context, MATRIX4); } + +"mat2x3" { return ES2_ident_ES3_keyword(context, MATRIX2x3); } +"mat3x2" { return ES2_ident_ES3_keyword(context, MATRIX3x2); } +"mat2x4" { return ES2_ident_ES3_keyword(context, MATRIX2x4); } +"mat4x2" { return ES2_ident_ES3_keyword(context, MATRIX4x2); } +"mat3x4" { return ES2_ident_ES3_keyword(context, MATRIX3x4); } +"mat4x3" { return ES2_ident_ES3_keyword(context, MATRIX4x3); } + "vec2" { return VEC2; } "vec3" { return VEC3; } "vec4" { return VEC4; } @@ -120,70 +149,160 @@ O [0-7] "bvec2" { return BVEC2; } "bvec3" { return BVEC3; } "bvec4" { return BVEC4; } - -"sampler2D" { return SAMPLER2D; } -"samplerCube" { return SAMPLERCUBE; } -"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; } -"sampler2DRect" { return SAMPLER2DRECT; } +"uvec2" { return ES2_ident_ES3_keyword(context, UVEC2); } +"uvec3" { return ES2_ident_ES3_keyword(context, UVEC3); } +"uvec4" { return ES2_ident_ES3_keyword(context, UVEC4); } + +"sampler2D" { return SAMPLER2D; } +"samplerCube" { return SAMPLERCUBE; } +"samplerExternalOES" { return SAMPLER_EXTERNAL_OES; } +"sampler3D" { return ES2_reserved_ES3_keyword(context, SAMPLER3D); } +"sampler3DRect" { return ES2_reserved_ES3_keyword(context, SAMPLER3DRECT); } +"sampler2DRect" { return SAMPLER2DRECT; } +"sampler2DArray" { return ES2_ident_ES3_keyword(context, SAMPLER2DARRAY); } +"isampler2D" { return ES2_ident_ES3_keyword(context, ISAMPLER2D); } +"isampler3D" { return ES2_ident_ES3_keyword(context, ISAMPLER3D); } +"isamplerCube" { return ES2_ident_ES3_keyword(context, ISAMPLERCUBE); } +"isampler2DArray" { return ES2_ident_ES3_keyword(context, ISAMPLER2DARRAY); } +"usampler2D" { return ES2_ident_ES3_keyword(context, USAMPLER2D); } +"usampler3D" { return ES2_ident_ES3_keyword(context, USAMPLER3D); } +"usamplerCube" { return ES2_ident_ES3_keyword(context, USAMPLERCUBE); } +"usampler2DArray" { return ES2_ident_ES3_keyword(context, USAMPLER2DARRAY); } +"sampler2DShadow" { return ES2_reserved_ES3_keyword(context, SAMPLER2DSHADOW); } +"samplerCubeShadow" { return ES2_ident_ES3_keyword(context, SAMPLERCUBESHADOW); } +"sampler2DArrayShadow" { return ES2_ident_ES3_keyword(context, SAMPLER2DARRAYSHADOW); } "struct" { return STRUCT; } -"asm" { return reserved_word(yyscanner); } - -"class" { return reserved_word(yyscanner); } -"union" { return reserved_word(yyscanner); } -"enum" { return reserved_word(yyscanner); } -"typedef" { return reserved_word(yyscanner); } -"template" { return reserved_word(yyscanner); } -"this" { return reserved_word(yyscanner); } -"packed" { return reserved_word(yyscanner); } - -"goto" { return reserved_word(yyscanner); } -"switch" { return reserved_word(yyscanner); } -"default" { return reserved_word(yyscanner); } - -"inline" { return reserved_word(yyscanner); } -"noinline" { return reserved_word(yyscanner); } -"volatile" { return reserved_word(yyscanner); } -"public" { return reserved_word(yyscanner); } -"static" { return reserved_word(yyscanner); } -"extern" { return reserved_word(yyscanner); } -"external" { return reserved_word(yyscanner); } -"interface" { return reserved_word(yyscanner); } -"flat" { return reserved_word(yyscanner); } - -"long" { return reserved_word(yyscanner); } -"short" { return reserved_word(yyscanner); } -"double" { return reserved_word(yyscanner); } -"half" { return reserved_word(yyscanner); } -"fixed" { return reserved_word(yyscanner); } -"unsigned" { return reserved_word(yyscanner); } -"superp" { return reserved_word(yyscanner); } - -"input" { return reserved_word(yyscanner); } -"output" { return reserved_word(yyscanner); } - -"hvec2" { return reserved_word(yyscanner); } -"hvec3" { return reserved_word(yyscanner); } -"hvec4" { return reserved_word(yyscanner); } -"dvec2" { return reserved_word(yyscanner); } -"dvec3" { return reserved_word(yyscanner); } -"dvec4" { return reserved_word(yyscanner); } -"fvec2" { return reserved_word(yyscanner); } -"fvec3" { return reserved_word(yyscanner); } -"fvec4" { return reserved_word(yyscanner); } - -"sampler1D" { return reserved_word(yyscanner); } -"sampler3D" { return reserved_word(yyscanner); } -"sampler1DShadow" { return reserved_word(yyscanner); } -"sampler2DShadow" { return reserved_word(yyscanner); } -"sampler3DRect" { return reserved_word(yyscanner); } -"sampler2DRectShadow" { return reserved_word(yyscanner); } - -"sizeof" { return reserved_word(yyscanner); } -"cast" { return reserved_word(yyscanner); } - -"namespace" { return reserved_word(yyscanner); } +"layout" { return ES2_ident_ES3_keyword(context, LAYOUT); } + + /* Reserved keywords for GLSL ES 3.00 that are not reserved for GLSL ES 1.00 */ +"coherent" | +"restrict" | +"readonly" | +"writeonly" | +"resource" | +"atomic_uint" | +"noperspective" | +"patch" | +"sample" | +"subroutine" | +"common" | +"partition" | +"active" | + +"filter" | +"image1D" | +"image2D" | +"image3D" | +"imageCube" | +"iimage1D" | +"iimage2D" | +"iimage3D" | +"iimageCube" | +"uimage1D" | +"uimage2D" | +"uimage3D" | +"uimageCube" | +"image1DArray" | +"image2DArray" | +"iimage1DArray" | +"iimage2DArray" | +"uimage1DArray" | +"uimage2DArray" | +"image1DShadow" | +"image2DShadow" | +"image1DArrayShadow" | +"image2DArrayShadow" | +"imageBuffer" | +"iimageBuffer" | +"uimageBuffer" | + +"sampler1DArray" | +"sampler1DArrayShadow" | +"isampler1D" | +"isampler1DArray" | +"usampler1D" | +"usampler1DArray" | +"isampler2DRect" | +"usampler2DRect" | +"samplerBuffer" | +"isamplerBuffer" | +"usamplerBuffer" | +"sampler2DMS" | +"isampler2DMS" | +"usampler2DMS" | +"sampler2DMSArray" | +"isampler2DMSArray" | +"usampler2DMSArray" { + if (context->shaderVersion < 300) { + yylval->lex.string = NewPoolTString(yytext); + return check_type(yyscanner); + } + return reserved_word(yyscanner); +} + + /* Reserved keywords in GLSL ES 1.00 that are not reserved in GLSL ES 3.00 */ +"packed" { + if (context->shaderVersion >= 300) + { + yylval->lex.string = NewPoolTString(yytext); + return check_type(yyscanner); + } + + return reserved_word(yyscanner); +} + + /* Reserved keywords */ +"asm" | + +"class" | +"union" | +"enum" | +"typedef" | +"template" | +"this" | + +"goto" | + +"inline" | +"noinline" | +"volatile" | +"public" | +"static" | +"extern" | +"external" | +"interface" | + +"long" | +"short" | +"double" | +"half" | +"fixed" | +"unsigned" | +"superp" | + +"input" | +"output" | + +"hvec2" | +"hvec3" | +"hvec4" | +"dvec2" | +"dvec3" | +"dvec4" | +"fvec2" | +"fvec3" | +"fvec4" | + +"sampler1D" | +"sampler1DShadow" | +"sampler2DRectShadow" | + +"sizeof" | +"cast" | + +"namespace" | "using" { return reserved_word(yyscanner); } {L}({L}|{D})* { @@ -195,10 +314,18 @@ O [0-7] 0{O}+ { return int_constant(yyscanner); } {D}+ { return int_constant(yyscanner); } +0[xX]{H}+[uU] { return uint_constant(context); } +0{O}+[uU] { return uint_constant(context); } +{D}+[uU] { return uint_constant(context); } + {D}+{E} { return float_constant(yyscanner); } {D}+"."{D}*({E})? { return float_constant(yyscanner); } "."{D}+({E})? { return float_constant(yyscanner); } +{D}+{E}[fF] { return floatsuffix_check(context); } +{D}+"."{D}*({E})?[fF] { return floatsuffix_check(context); } +"."{D}+({E})?[fF] { return floatsuffix_check(context); } + "+=" { return ADD_ASSIGN; } "-=" { return SUB_ASSIGN; } "*=" { return MUL_ASSIGN; } @@ -224,31 +351,31 @@ O [0-7] ";" { return SEMICOLON; } ("{"|"<%") { return LEFT_BRACE; } ("}"|"%>") { return RIGHT_BRACE; } -"," { return COMMA; } -":" { return COLON; } -"=" { return EQUAL; } -"(" { return LEFT_PAREN; } -")" { return RIGHT_PAREN; } -("["|"<:") { return LEFT_BRACKET; } -("]"|":>") { return RIGHT_BRACKET; } -"." { return DOT; } -"!" { return BANG; } -"-" { return DASH; } -"~" { return TILDE; } -"+" { return PLUS; } -"*" { return STAR; } -"/" { return SLASH; } -"%" { return PERCENT; } -"<" { return LEFT_ANGLE; } -">" { return RIGHT_ANGLE; } -"|" { return VERTICAL_BAR; } -"^" { return CARET; } -"&" { return AMPERSAND; } -"?" { return QUESTION; } +"," { return COMMA; } +":" { return COLON; } +"=" { return EQUAL; } +"(" { return LEFT_PAREN; } +")" { return RIGHT_PAREN; } +("["|"<:") { return LEFT_BRACKET; } +("]"|":>") { return RIGHT_BRACKET; } +"." { return DOT; } +"!" { return BANG; } +"-" { return DASH; } +"~" { return TILDE; } +"+" { return PLUS; } +"*" { return STAR; } +"/" { return SLASH; } +"%" { return PERCENT; } +"<" { return LEFT_ANGLE; } +">" { return RIGHT_ANGLE; } +"|" { return VERTICAL_BAR; } +"^" { return CARET; } +"&" { return AMPERSAND; } +"?" { return QUESTION; } [ \t\v\n\f\r] { } -<> { yyterminate(); } -. { assert(false); return 0; } +<> { yyterminate(); } +. { assert(false); return 0; } %% @@ -272,11 +399,12 @@ int check_type(yyscan_t yyscanner) { struct yyguts_t* yyg = (struct yyguts_t*) yyscanner; int token = IDENTIFIER; - TSymbol* symbol = yyextra->symbolTable.find(yytext); + TSymbol* symbol = yyextra->symbolTable.find(yytext, yyextra->shaderVersion); if (symbol && symbol->isVariable()) { TVariable* variable = static_cast(symbol); - if (variable->isUserType()) + if (variable->isUserType()) { token = TYPE_NAME; + } } yylval->lex.symbol = symbol; return token; @@ -290,6 +418,80 @@ int reserved_word(yyscan_t yyscanner) { return 0; } +int ES2_reserved_ES3_keyword(TParseContext *context, int token) +{ + yyscan_t yyscanner = (yyscan_t) context->scanner; + + if (context->shaderVersion < 300) + { + return reserved_word(yyscanner); + } + + return token; +} + +int ES2_keyword_ES3_reserved(TParseContext *context, int token) +{ + yyscan_t yyscanner = (yyscan_t) context->scanner; + + if (context->shaderVersion >= 300) + { + return reserved_word(yyscanner); + } + + return token; +} + +int ES2_ident_ES3_keyword(TParseContext *context, int token) +{ + struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; + yyscan_t yyscanner = (yyscan_t) context->scanner; + + // not a reserved word in GLSL ES 1.00, so could be used as an identifier/type name + if (context->shaderVersion < 300) + { + yylval->lex.string = NewPoolTString(yytext); + return check_type(yyscanner); + } + + return token; +} + +int uint_constant(TParseContext *context) +{ + struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; + yyscan_t yyscanner = (yyscan_t) context->scanner; + + if (context->shaderVersion < 300) + { + context->error(*yylloc, "Unsigned integers are unsupported prior to GLSL ES 3.00", yytext, ""); + context->recover(); + return 0; + } + + if (!atoi_clamp(yytext, &(yylval->lex.i))) + yyextra->warning(*yylloc, "Integer overflow", yytext, ""); + + return UINTCONSTANT; +} + +int floatsuffix_check(TParseContext* context) +{ + struct yyguts_t* yyg = (struct yyguts_t*) context->scanner; + + if (context->shaderVersion < 300) + { + context->error(*yylloc, "Floating-point suffix unsupported prior to GLSL ES 3.00", yytext); + context->recover(); + return 0; + } + + if (!atof_clamp(yytext, &(yylval->lex.f))) + yyextra->warning(*yylloc, "Float overflow", yytext, ""); + + return(FLOATCONSTANT); +} + void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) { context->error(*lloc, reason, yyget_text(context->scanner)); context->recover(); @@ -339,7 +541,6 @@ int glslang_scan(size_t count, const char* const string[], const int length[], // Initialize preprocessor. if (!context->preprocessor.init(count, string, length)) return 1; - context->preprocessor.setMaxTokenLength(SH_MAX_TOKEN_LENGTH); // Define extension macros. const TExtensionBehavior& extBehavior = context->extensionBehavior(); @@ -350,6 +551,8 @@ int glslang_scan(size_t count, const char* const string[], const int length[], if (context->fragmentPrecisionHigh) context->preprocessor.predefineMacro("GL_FRAGMENT_PRECISION_HIGH", 1); + context->preprocessor.setMaxTokenSize(GetGlobalMaxTokenSize(context->shaderSpec)); + return 0; } diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.y b/src/3rdparty/angle/src/compiler/translator/glslang.y index 7614ff3447..fb2d835368 100644 --- a/src/3rdparty/angle/src/compiler/translator/glslang.y +++ b/src/3rdparty/angle/src/compiler/translator/glslang.y @@ -1,6 +1,6 @@ /* // -// Copyright (c) 2002-2013 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. // @@ -15,7 +15,7 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). %{ // -// Copyright (c) 2002-2010 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. // @@ -34,6 +34,7 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). #pragma warning(disable: 4701) #endif +#include "angle_gl.h" #include "compiler/translator/SymbolTable.h" #include "compiler/translator/ParseContext.h" #include "GLSLANG/ShaderLang.h" @@ -41,8 +42,8 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). #define YYENABLE_NLS 0 #define YYLEX_PARAM context->scanner -%} +%} %expect 1 /* One shift reduce conflict because of if | else */ %pure-parser %parse-param {TParseContext* context} @@ -51,7 +52,6 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). %code requires { #define YYLTYPE TSourceLoc #define YYLTYPE_IS_DECLARED 1 -#define SH_MAX_TOKEN_LENGTH 256 // WebGL spec. } %union { @@ -60,6 +60,7 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). TString *string; float f; int i; + unsigned int u; bool b; }; TSymbol* symbol; @@ -75,6 +76,7 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). union { TPublicType type; TPrecision precision; + TLayoutQualifier layoutQualifier; TQualifier qualifier; TFunction* function; TParameter param; @@ -105,29 +107,50 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason) } while (0) #define VERTEX_ONLY(S, L) { \ - if (context->shaderType != SH_VERTEX_SHADER) { \ + if (context->shaderType != GL_VERTEX_SHADER) { \ context->error(L, " supported in vertex shaders only ", S); \ context->recover(); \ } \ } #define FRAG_ONLY(S, L) { \ - if (context->shaderType != SH_FRAGMENT_SHADER) { \ + if (context->shaderType != GL_FRAGMENT_SHADER) { \ context->error(L, " supported in fragment shaders only ", S); \ context->recover(); \ } \ } + +#define ES2_ONLY(S, L) { \ + if (context->shaderVersion != 100) { \ + context->error(L, " supported in GLSL ES 1.00 only ", S); \ + context->recover(); \ + } \ +} + +#define ES3_ONLY(TOKEN, LINE, REASON) { \ + if (context->shaderVersion != 300) { \ + context->error(LINE, REASON " supported in GLSL ES 3.00 only ", TOKEN); \ + context->recover(); \ + } \ +} %} %token INVARIANT HIGH_PRECISION MEDIUM_PRECISION LOW_PRECISION PRECISION -%token ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE -%token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN -%token BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4 +%token ATTRIBUTE CONST_QUAL BOOL_TYPE FLOAT_TYPE INT_TYPE UINT_TYPE +%token BREAK CONTINUE DO ELSE FOR IF DISCARD RETURN SWITCH CASE DEFAULT +%token BVEC2 BVEC3 BVEC4 IVEC2 IVEC3 IVEC4 VEC2 VEC3 VEC4 UVEC2 UVEC3 UVEC4 %token MATRIX2 MATRIX3 MATRIX4 IN_QUAL OUT_QUAL INOUT_QUAL UNIFORM VARYING +%token MATRIX2x3 MATRIX3x2 MATRIX2x4 MATRIX4x2 MATRIX3x4 MATRIX4x3 +%token CENTROID FLAT SMOOTH %token STRUCT VOID_TYPE WHILE -%token SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT - -%token IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT BOOLCONSTANT +%token SAMPLER2D SAMPLERCUBE SAMPLER_EXTERNAL_OES SAMPLER2DRECT SAMPLER2DARRAY +%token ISAMPLER2D ISAMPLER3D ISAMPLERCUBE ISAMPLER2DARRAY +%token USAMPLER2D USAMPLER3D USAMPLERCUBE USAMPLER2DARRAY +%token SAMPLER3D SAMPLER3DRECT SAMPLER2DSHADOW SAMPLERCUBESHADOW SAMPLER2DARRAYSHADOW +%token LAYOUT + +%token IDENTIFIER TYPE_NAME FLOATCONSTANT INTCONSTANT UINTCONSTANT BOOLCONSTANT +%token FIELD_SELECTION %token LEFT_OP RIGHT_OP %token INC_OP DEC_OP LE_OP GE_OP EQ_OP NE_OP %token AND_OP OR_OP XOR_OP MUL_ASSIGN DIV_ASSIGN ADD_ASSIGN @@ -160,10 +183,11 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason) %type single_declaration init_declarator_list %type parameter_declaration parameter_declarator parameter_type_specifier -%type parameter_qualifier +%type parameter_qualifier parameter_type_qualifier +%type layout_qualifier layout_qualifier_id_list layout_qualifier_id %type precision_qualifier -%type type_qualifier fully_specified_type type_specifier +%type type_qualifier fully_specified_type type_specifier storage_qualifier interpolation_qualifier %type type_specifier_no_prec type_specifier_nonarray %type struct_specifier %type struct_declarator @@ -173,6 +197,8 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason) %type function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype %type function_call_or_method +%type enter_struct + %start translation_unit %% @@ -200,7 +226,7 @@ variable_identifier { variable = static_cast(symbol); - if (context->symbolTable.findBuiltIn(variable->getName()) && + if (context->symbolTable.findBuiltIn(variable->getName(), context->shaderVersion) && !variable->getExtension().empty() && context->extensionErrorCheck(@1, variable->getExtension())) { @@ -212,7 +238,7 @@ variable_identifier { TType type(EbtFloat, EbpUndefined); TVariable *fakeVariable = new TVariable($1.string, type); - context->symbolTable.insert(*fakeVariable); + context->symbolTable.declare(fakeVariable); variable = fakeVariable; } @@ -244,6 +270,11 @@ primary_expression unionArray->setIConst($1.i); $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @1); } + | UINTCONSTANT { + ConstantUnion *unionArray = new ConstantUnion[1]; + unionArray->setUConst($1.u); + $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtUInt, EbpUndefined, EvqConst), @1); + } | FLOATCONSTANT { ConstantUnion *unionArray = new ConstantUnion[1]; unionArray->setFConst($1.f); @@ -270,104 +301,12 @@ postfix_expression $$ = $1; } | postfix_expression DOT identifier { - if ($1->isArray()) { - context->error(@3, "cannot apply dot operator to an array", "."); - context->recover(); - } - - if ($1->isVector()) { - TVectorFields fields; - if (! context->parseVectorFields(*$3.string, $1->getNominalSize(), fields, @3)) { - fields.num = 1; - fields.offsets[0] = 0; - context->recover(); - } - - if ($1->getType().getQualifier() == EvqConst) { // constant folding for vector fields - $$ = context->addConstVectorNode(fields, $1, @3); - if ($$ == 0) { - context->recover(); - $$ = $1; - } - else - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqConst, (int) (*$3.string).size())); - } else { - TString vectorString = *$3.string; - TIntermTyped* index = context->intermediate.addSwizzle(fields, @3); - $$ = context->intermediate.addIndex(EOpVectorSwizzle, $1, index, @2); - $$->setType(TType($1->getBasicType(), $1->getPrecision(), EvqTemporary, (int) vectorString.size())); - } - } else if ($1->isMatrix()) { - TMatrixFields fields; - if (! context->parseMatrixFields(*$3.string, $1->getNominalSize(), fields, @3)) { - fields.wholeRow = false; - fields.wholeCol = false; - fields.row = 0; - fields.col = 0; - context->recover(); - } - - if (fields.wholeRow || fields.wholeCol) { - context->error(@2, " non-scalar fields not implemented yet", "."); - context->recover(); - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setIConst(0); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3); - $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2); - $$->setType(TType($1->getBasicType(), $1->getPrecision(),EvqTemporary, $1->getNominalSize())); - } else { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setIConst(fields.col * $1->getNominalSize() + fields.row); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst), @3); - $$ = context->intermediate.addIndex(EOpIndexDirect, $1, index, @2); - $$->setType(TType($1->getBasicType(), $1->getPrecision())); - } - } else if ($1->getBasicType() == EbtStruct) { - bool fieldFound = false; - const TFieldList& fields = $1->getType().getStruct()->fields(); - unsigned int i; - for (i = 0; i < fields.size(); ++i) { - if (fields[i]->name() == *$3.string) { - fieldFound = true; - break; - } - } - if (fieldFound) { - if ($1->getType().getQualifier() == EvqConst) { - $$ = context->addConstStruct(*$3.string, $1, @2); - if ($$ == 0) { - context->recover(); - $$ = $1; - } - else { - $$->setType(*fields[i]->type()); - // change the qualifier of the return type, not of the structure field - // as the structure definition is shared between various structures. - $$->getTypePointer()->setQualifier(EvqConst); - } - } else { - ConstantUnion *unionArray = new ConstantUnion[1]; - unionArray->setIConst(i); - TIntermTyped* index = context->intermediate.addConstantUnion(unionArray, *fields[i]->type(), @3); - $$ = context->intermediate.addIndex(EOpIndexDirectStruct, $1, index, @2); - $$->setType(*fields[i]->type()); - } - } else { - context->error(@2, " no such field in structure", $3.string->c_str()); - context->recover(); - $$ = $1; - } - } else { - context->error(@2, " field selection requires structure, vector, or matrix on left hand side", $3.string->c_str()); - context->recover(); - $$ = $1; - } - // don't delete $3.string, it's from the pool + $$ = context->addFieldSelectionExpression($1, @2, *$3.string, @3); } | postfix_expression INC_OP { if (context->lValueErrorCheck(@2, "++", $1)) context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2, context->symbolTable); + $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2); if ($$ == 0) { context->unaryOpError(@2, "++", $1->getCompleteString()); context->recover(); @@ -377,7 +316,7 @@ postfix_expression | postfix_expression DEC_OP { if (context->lValueErrorCheck(@2, "--", $1)) context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2, context->symbolTable); + $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2); if ($$ == 0) { context->unaryOpError(@2, "--", $1->getCompleteString()); context->recover(); @@ -427,7 +366,7 @@ function_call // const TFunction* fnCandidate; bool builtIn; - fnCandidate = context->findFunction(@1, fnCall, &builtIn); + fnCandidate = context->findFunction(@1, fnCall, context->shaderVersion, &builtIn); if (fnCandidate) { // // A declared function. @@ -445,7 +384,7 @@ function_call // // Treat it like a built-in unary operator. // - $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1, context->symbolTable); + $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1); if ($$ == 0) { std::stringstream extraInfoStream; extraInfoStream << "built in unary operator function. Type: " << static_cast($1.intermNode)->getCompleteString(); @@ -473,7 +412,7 @@ function_call for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) { qual = fnCandidate->getParam(i).type->getQualifier(); if (qual == EvqOut || qual == EvqInOut) { - if (context->lValueErrorCheck($$->getLine(), "assign", $$->getAsAggregate()->getSequence()[i]->getAsTyped())) { + if (context->lValueErrorCheck($$->getLine(), "assign", (*($$->getAsAggregate()->getSequence()))[i]->getAsTyped())) { context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error"); context->recover(); } @@ -550,59 +489,7 @@ function_call_header function_identifier : type_specifier_nonarray { - // - // Constructor - // - TOperator op = EOpNull; - if ($1.userDef) { - op = EOpConstructStruct; - } else { - switch ($1.type) { - case EbtFloat: - if ($1.matrix) { - switch($1.size) { - case 2: op = EOpConstructMat2; break; - case 3: op = EOpConstructMat3; break; - case 4: op = EOpConstructMat4; break; - } - } else { - switch($1.size) { - case 1: op = EOpConstructFloat; break; - case 2: op = EOpConstructVec2; break; - case 3: op = EOpConstructVec3; break; - case 4: op = EOpConstructVec4; break; - } - } - break; - case EbtInt: - switch($1.size) { - case 1: op = EOpConstructInt; break; - case 2: op = EOpConstructIVec2; break; - case 3: op = EOpConstructIVec3; break; - case 4: op = EOpConstructIVec4; break; - } - break; - case EbtBool: - switch($1.size) { - case 1: op = EOpConstructBool; break; - case 2: op = EOpConstructBVec2; break; - case 3: op = EOpConstructBVec3; break; - case 4: op = EOpConstructBVec4; break; - } - break; - default: break; - } - if (op == EOpNull) { - context->error(@1, "cannot construct this type", getBasicString($1.type)); - context->recover(); - $1.type = EbtFloat; - op = EOpConstructFloat; - } - } - TString tempString; - TType type($1); - TFunction *function = new TFunction(&tempString, type, op); - $$ = function; + $$ = context->addConstructorFunc($1); } | IDENTIFIER { if (context->reservedErrorCheck(@1, *$1.string)) @@ -620,7 +507,7 @@ unary_expression | INC_OP unary_expression { if (context->lValueErrorCheck(@1, "++", $2)) context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1, context->symbolTable); + $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1); if ($$ == 0) { context->unaryOpError(@1, "++", $2->getCompleteString()); context->recover(); @@ -630,7 +517,7 @@ unary_expression | DEC_OP unary_expression { if (context->lValueErrorCheck(@1, "--", $2)) context->recover(); - $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1, context->symbolTable); + $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1); if ($$ == 0) { context->unaryOpError(@1, "--", $2->getCompleteString()); context->recover(); @@ -639,7 +526,7 @@ unary_expression } | unary_operator unary_expression { if ($1.op != EOpNull) { - $$ = context->intermediate.addUnaryMath($1.op, $2, @1, context->symbolTable); + $$ = context->intermediate.addUnaryMath($1.op, $2, @1); if ($$ == 0) { const char* errorOp = ""; switch($1.op) { @@ -667,7 +554,7 @@ unary_operator multiplicative_expression : unary_expression { $$ = $1; } | multiplicative_expression STAR unary_expression { - $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2); if ($$ == 0) { context->binaryOpError(@2, "*", $1->getCompleteString(), $3->getCompleteString()); context->recover(); @@ -675,7 +562,7 @@ multiplicative_expression } } | multiplicative_expression SLASH unary_expression { - $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2); if ($$ == 0) { context->binaryOpError(@2, "/", $1->getCompleteString(), $3->getCompleteString()); context->recover(); @@ -687,7 +574,7 @@ multiplicative_expression additive_expression : multiplicative_expression { $$ = $1; } | additive_expression PLUS multiplicative_expression { - $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2); if ($$ == 0) { context->binaryOpError(@2, "+", $1->getCompleteString(), $3->getCompleteString()); context->recover(); @@ -695,7 +582,7 @@ additive_expression } } | additive_expression DASH multiplicative_expression { - $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2); if ($$ == 0) { context->binaryOpError(@2, "-", $1->getCompleteString(), $3->getCompleteString()); context->recover(); @@ -711,7 +598,7 @@ shift_expression relational_expression : shift_expression { $$ = $1; } | relational_expression LEFT_ANGLE shift_expression { - $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2); if ($$ == 0) { context->binaryOpError(@2, "<", $1->getCompleteString(), $3->getCompleteString()); context->recover(); @@ -721,7 +608,7 @@ relational_expression } } | relational_expression RIGHT_ANGLE shift_expression { - $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2); if ($$ == 0) { context->binaryOpError(@2, ">", $1->getCompleteString(), $3->getCompleteString()); context->recover(); @@ -731,7 +618,7 @@ relational_expression } } | relational_expression LE_OP shift_expression { - $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2); if ($$ == 0) { context->binaryOpError(@2, "<=", $1->getCompleteString(), $3->getCompleteString()); context->recover(); @@ -741,7 +628,7 @@ relational_expression } } | relational_expression GE_OP shift_expression { - $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2); if ($$ == 0) { context->binaryOpError(@2, ">=", $1->getCompleteString(), $3->getCompleteString()); context->recover(); @@ -755,7 +642,7 @@ relational_expression equality_expression : relational_expression { $$ = $1; } | equality_expression EQ_OP relational_expression { - $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2); if ($$ == 0) { context->binaryOpError(@2, "==", $1->getCompleteString(), $3->getCompleteString()); context->recover(); @@ -765,7 +652,7 @@ equality_expression } } | equality_expression NE_OP relational_expression { - $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2); if ($$ == 0) { context->binaryOpError(@2, "!=", $1->getCompleteString(), $3->getCompleteString()); context->recover(); @@ -791,7 +678,7 @@ inclusive_or_expression logical_and_expression : inclusive_or_expression { $$ = $1; } | logical_and_expression AND_OP inclusive_or_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2); if ($$ == 0) { context->binaryOpError(@2, "&&", $1->getCompleteString(), $3->getCompleteString()); context->recover(); @@ -805,7 +692,7 @@ logical_and_expression logical_xor_expression : logical_and_expression { $$ = $1; } | logical_xor_expression XOR_OP logical_and_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2); if ($$ == 0) { context->binaryOpError(@2, "^^", $1->getCompleteString(), $3->getCompleteString()); context->recover(); @@ -819,7 +706,7 @@ logical_xor_expression logical_or_expression : logical_xor_expression { $$ = $1; } | logical_or_expression OR_OP logical_xor_expression { - $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2, context->symbolTable); + $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2); if ($$ == 0) { context->binaryOpError(@2, "||", $1->getCompleteString(), $3->getCompleteString()); context->recover(); @@ -892,6 +779,14 @@ constant_expression } ; +enter_struct + : IDENTIFIER LEFT_BRACE { + if (context->enterStructDeclaration(@1, *$1.string)) + context->recover(); + $$ = $1; + } + ; + declaration : function_prototype SEMICOLON { TFunction &function = *($1.function); @@ -926,7 +821,7 @@ declaration $$ = $1.intermAggregate; } | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { - if (($2 == EbpHigh) && (context->shaderType == SH_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) { + if (($2 == EbpHigh) && (context->shaderType == GL_FRAGMENT_SHADER) && !context->fragmentPrecisionHigh) { context->error(@1, "precision is not supported in fragment shader", "highp"); context->recover(); } @@ -936,6 +831,22 @@ declaration } $$ = 0; } + | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE SEMICOLON { + ES3_ONLY(getQualifierString($1.qualifier), @1, "interface blocks"); + $$ = context->addInterfaceBlock($1, @2, *$2.string, $3, NULL, @$, NULL, @$); + } + | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON { + ES3_ONLY(getQualifierString($1.qualifier), @1, "interface blocks"); + $$ = context->addInterfaceBlock($1, @2, *$2.string, $3, $5.string, @5, NULL, @$); + } + | type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET SEMICOLON { + ES3_ONLY(getQualifierString($1.qualifier), @1, "interface blocks"); + $$ = context->addInterfaceBlock($1, @2, *$2.string, $3, $5.string, @5, $7, @6); + } + | type_qualifier SEMICOLON { + context->parseGlobalLayoutQualifier($1); + $$ = 0; + } ; function_prototype @@ -948,7 +859,7 @@ function_prototype // // Redeclarations are allowed. But, return types and parameter qualifiers must match. // - TFunction* prevDec = static_cast(context->symbolTable.find($1->getMangledName())); + TFunction* prevDec = static_cast(context->symbolTable.find($1->getMangledName(), context->shaderVersion)); if (prevDec) { if (prevDec->getReturnType() != $1->getReturnType()) { context->error(@2, "overloaded functions must have the same return type", $1->getReturnType().getBasicString()); @@ -965,7 +876,7 @@ function_prototype // // Check for previously declared variables using the same name. // - TSymbol *prevSym = context->symbolTable.find($1->getName()); + TSymbol *prevSym = context->symbolTable.find($1->getName(), context->shaderVersion); if (prevSym) { if (!prevSym->isFunction()) @@ -977,7 +888,8 @@ function_prototype else { // Insert the unmangled name to detect potential future redefinition as a variable. - context->symbolTable.getOuterLevel()->insert($1->getName(), *$1); + TFunction *function = new TFunction(NewPoolTString($1->getName().c_str()), $1->getReturnType()); + context->symbolTable.getOuterLevel()->insert(function); } // @@ -989,7 +901,7 @@ function_prototype // We're at the inner scope level of the function's arguments and body statement. // Add the function prototype to the surrounding scope instead. - context->symbolTable.getOuterLevel()->insert(*$$.function); + context->symbolTable.getOuterLevel()->insert($$.function); } ; @@ -1092,9 +1004,9 @@ parameter_declaration // // Type + name // - : type_qualifier parameter_qualifier parameter_declarator { + : parameter_type_qualifier parameter_qualifier parameter_declarator { $$ = $3; - if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type)) + if (context->paramErrorCheck(@3, $1, $2, $$.param.type)) context->recover(); } | parameter_qualifier parameter_declarator { @@ -1107,9 +1019,9 @@ parameter_declaration // // Only type // - | type_qualifier parameter_qualifier parameter_type_specifier { + | parameter_type_qualifier parameter_qualifier parameter_type_specifier { $$ = $3; - if (context->paramErrorCheck(@3, $1.qualifier, $2, $$.param.type)) + if (context->paramErrorCheck(@3, $1, $2, $$.param.type)) context->recover(); } | parameter_qualifier parameter_type_specifier { @@ -1148,173 +1060,46 @@ init_declarator_list $$ = $1; } | init_declarator_list COMMA identifier { - if ($1.type.type == EbtInvariant && !$3.symbol) - { - context->error(@3, "undeclared identifier declared as invariant", $3.string->c_str()); - context->recover(); - } - - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$3.string, TType($1.type), @3); - $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, symbol, @3); - - if (context->structQualifierErrorCheck(@3, $$.type)) - context->recover(); - - if (context->nonInitConstErrorCheck(@3, *$3.string, $$.type, false)) - context->recover(); - - TVariable* variable = 0; - if (context->nonInitErrorCheck(@3, *$3.string, $$.type, variable)) - context->recover(); - if (symbol && variable) - symbol->setId(variable->getUniqueId()); + $$ = $1; + $$.intermAggregate = context->parseDeclarator($$.type, $1.intermAggregate, $3.symbol, @3, *$3.string); } | init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET { - if (context->structQualifierErrorCheck(@3, $1.type)) - context->recover(); - - if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true)) - context->recover(); - $$ = $1; - - if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type)) - context->recover(); - else { - $1.type.setArray(true); - TVariable* variable; - if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable)) - context->recover(); - } + context->parseArrayDeclarator($$.type, @3, *$3.string, @4, NULL, NULL); } | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { - if (context->structQualifierErrorCheck(@3, $1.type)) - context->recover(); - - if (context->nonInitConstErrorCheck(@3, *$3.string, $1.type, true)) - context->recover(); - $$ = $1; - - if (context->arrayTypeErrorCheck(@4, $1.type) || context->arrayQualifierErrorCheck(@4, $1.type)) - context->recover(); - else { - int size; - if (context->arraySizeErrorCheck(@4, $5, size)) - context->recover(); - $1.type.setArray(true, size); - TVariable* variable = 0; - if (context->arrayErrorCheck(@4, *$3.string, $1.type, variable)) - context->recover(); - TType type = TType($1.type); - type.setArraySize(size); - $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, context->intermediate.addSymbol(variable ? variable->getUniqueId() : 0, *$3.string, type, @3), @3); - } + $$.intermAggregate = context->parseArrayDeclarator($$.type, @3, *$3.string, @4, $1.intermNode, $5); } | init_declarator_list COMMA identifier EQUAL initializer { - if (context->structQualifierErrorCheck(@3, $1.type)) - context->recover(); - $$ = $1; - - TIntermNode* intermNode; - if (!context->executeInitializer(@3, *$3.string, $1.type, $5, intermNode)) { - // - // build the intermediate representation - // - if (intermNode) - $$.intermAggregate = context->intermediate.growAggregate($1.intermNode, intermNode, @4); - else - $$.intermAggregate = $1.intermAggregate; - } else { - context->recover(); - $$.intermAggregate = 0; - } + $$.intermAggregate = context->parseInitDeclarator($$.type, $1.intermAggregate, @3, *$3.string, @4, $5); } ; single_declaration : fully_specified_type { $$.type = $1; - $$.intermAggregate = context->intermediate.makeAggregate(context->intermediate.addSymbol(0, "", TType($1), @1), @1); + $$.intermAggregate = context->parseSingleDeclaration($$.type, @1, ""); } | fully_specified_type identifier { - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); - - if (context->structQualifierErrorCheck(@2, $$.type)) - context->recover(); - - if (context->nonInitConstErrorCheck(@2, *$2.string, $$.type, false)) - context->recover(); - - $$.type = $1; - - TVariable* variable = 0; - if (context->nonInitErrorCheck(@2, *$2.string, $$.type, variable)) - context->recover(); - if (variable && symbol) - symbol->setId(variable->getUniqueId()); + $$.type = $1; + $$.intermAggregate = context->parseSingleDeclaration($$.type, @2, *$2.string); } | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET { context->error(@2, "unsized array declarations not supported", $2.string->c_str()); context->recover(); - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, TType($1), @2); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); $$.type = $1; + $$.intermAggregate = context->parseSingleDeclaration($$.type, @2, *$2.string); } | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { - TType type = TType($1); - int size; - if (context->arraySizeErrorCheck(@2, $4, size)) - context->recover(); - type.setArraySize(size); - TIntermSymbol* symbol = context->intermediate.addSymbol(0, *$2.string, type, @2); - $$.intermAggregate = context->intermediate.makeAggregate(symbol, @2); - - if (context->structQualifierErrorCheck(@2, $1)) - context->recover(); - - if (context->nonInitConstErrorCheck(@2, *$2.string, $1, true)) - context->recover(); - $$.type = $1; - - if (context->arrayTypeErrorCheck(@3, $1) || context->arrayQualifierErrorCheck(@3, $1)) - context->recover(); - else { - int size; - if (context->arraySizeErrorCheck(@3, $4, size)) - context->recover(); - - $1.setArray(true, size); - TVariable* variable = 0; - if (context->arrayErrorCheck(@3, *$2.string, $1, variable)) - context->recover(); - if (variable && symbol) - symbol->setId(variable->getUniqueId()); - } + $$.intermAggregate = context->parseSingleArrayDeclaration($$.type, @2, *$2.string, @3, $4); } | fully_specified_type identifier EQUAL initializer { - if (context->structQualifierErrorCheck(@2, $1)) - context->recover(); - $$.type = $1; - - TIntermNode* intermNode; - if (!context->executeInitializer(@2, *$2.string, $1, $4, intermNode)) { - // - // Build intermediate representation - // - if(intermNode) - $$.intermAggregate = context->intermediate.makeAggregate(intermNode, @3); - else - $$.intermAggregate = 0; - } else { - context->recover(); - $$.intermAggregate = 0; - } + $$.intermAggregate = context->parseSingleInitDeclaration($$.type, @2, *$2.string, @3, $4); } | INVARIANT IDENTIFIER { VERTEX_ONLY("invariant declaration", @1); @@ -1347,57 +1132,113 @@ fully_specified_type } } | type_qualifier type_specifier { - if ($2.array) { - context->error(@2, "not supported", "first-class array"); - context->recover(); - $2.setArray(false); - } + $$ = context->addFullySpecifiedType($1.qualifier, $1.layoutQualifier, $2); + } + ; - if ($1.qualifier == EvqAttribute && - ($2.type == EbtBool || $2.type == EbtInt)) { - context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier)); - context->recover(); - } - if (($1.qualifier == EvqVaryingIn || $1.qualifier == EvqVaryingOut) && - ($2.type == EbtBool || $2.type == EbtInt)) { - context->error(@2, "cannot be bool or int", getQualifierString($1.qualifier)); - context->recover(); - } - $$ = $2; - $$.qualifier = $1.qualifier; +interpolation_qualifier + : SMOOTH { + $$.qualifier = EvqSmooth; + } + | FLAT { + $$.qualifier = EvqFlat; } ; -type_qualifier +parameter_type_qualifier : CONST_QUAL { - $$.setBasic(EbtVoid, EvqConst, @1); + $$ = EvqConst; } - | ATTRIBUTE { + ; + +type_qualifier + : ATTRIBUTE { VERTEX_ONLY("attribute", @1); + ES2_ONLY("attribute", @1); if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "attribute")) context->recover(); $$.setBasic(EbtVoid, EvqAttribute, @1); } | VARYING { + ES2_ONLY("varying", @1); if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "varying")) context->recover(); - if (context->shaderType == SH_VERTEX_SHADER) + if (context->shaderType == GL_VERTEX_SHADER) $$.setBasic(EbtVoid, EvqVaryingOut, @1); else $$.setBasic(EbtVoid, EvqVaryingIn, @1); } | INVARIANT VARYING { + ES2_ONLY("varying", @1); if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "invariant varying")) context->recover(); - if (context->shaderType == SH_VERTEX_SHADER) + if (context->shaderType == GL_VERTEX_SHADER) $$.setBasic(EbtVoid, EvqInvariantVaryingOut, @1); else $$.setBasic(EbtVoid, EvqInvariantVaryingIn, @1); } + | storage_qualifier { + if ($1.qualifier != EvqConst && !context->symbolTable.atGlobalLevel()) { + context->error(@1, "Local variables can only use the const storage qualifier.", getQualifierString($1.qualifier)); + context->recover(); + } else { + $$.setBasic(EbtVoid, $1.qualifier, @1); + } + } + | interpolation_qualifier storage_qualifier { + $$ = context->joinInterpolationQualifiers(@1, $1.qualifier, @2, $2.qualifier); + } + | interpolation_qualifier { + context->error(@1, "interpolation qualifier requires a fragment 'in' or vertex 'out' storage qualifier", getInterpolationString($1.qualifier)); + context->recover(); + + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtVoid, qual, @1); + } + | layout_qualifier { + $$.qualifier = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.layoutQualifier = $1; + } + | layout_qualifier storage_qualifier { + $$.setBasic(EbtVoid, $2.qualifier, @2); + $$.layoutQualifier = $1; + } + ; + +storage_qualifier + : CONST_QUAL { + $$.qualifier = EvqConst; + } + | IN_QUAL { + ES3_ONLY("in", @1, "storage qualifier"); + $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentIn : EvqVertexIn; + } + | OUT_QUAL { + ES3_ONLY("out", @1, "storage qualifier"); + $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqVertexOut; + } + | CENTROID IN_QUAL { + ES3_ONLY("centroid in", @1, "storage qualifier"); + if (context->shaderType == GL_VERTEX_SHADER) + { + context->error(@1, "invalid storage qualifier", "it is an error to use 'centroid in' in the vertex shader"); + context->recover(); + } + $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqCentroidIn : EvqVertexIn; + } + | CENTROID OUT_QUAL { + ES3_ONLY("centroid out", @1, "storage qualifier"); + if (context->shaderType == GL_FRAGMENT_SHADER) + { + context->error(@1, "invalid storage qualifier", "it is an error to use 'centroid out' in the fragment shader"); + context->recover(); + } + $$.qualifier = (context->shaderType == GL_FRAGMENT_SHADER) ? EvqFragmentOut : EvqCentroidOut; + } | UNIFORM { if (context->globalErrorCheck(@1, context->symbolTable.atGlobalLevel(), "uniform")) context->recover(); - $$.setBasic(EbtVoid, EvqUniform, @1); + $$.qualifier = EvqUniform; } ; @@ -1415,6 +1256,11 @@ type_specifier | precision_qualifier type_specifier_no_prec { $$ = $2; $$.precision = $1; + + if (!SupportsPrecision($2.type)) { + context->error(@1, "illegal type for precision qualifier", getBasicString($2.type)); + context->recover(); + } } ; @@ -1430,6 +1276,34 @@ precision_qualifier } ; +layout_qualifier + : LAYOUT LEFT_PAREN layout_qualifier_id_list RIGHT_PAREN { + ES3_ONLY("layout", @1, "qualifier"); + $$ = $3; + } + ; + +layout_qualifier_id_list + : layout_qualifier_id { + $$ = $1; + } + | layout_qualifier_id_list COMMA layout_qualifier_id { + $$ = context->joinLayoutQualifiers($1, $3); + } + ; + +layout_qualifier_id + : IDENTIFIER { + $$ = context->parseLayoutQualifier(*$1.string, @1); + } + | IDENTIFIER EQUAL INTCONSTANT { + $$ = context->parseLayoutQualifier(*$1.string, @1, *$3.string, $3.i, @3); + } + | IDENTIFIER EQUAL UINTCONSTANT { + $$ = context->parseLayoutQualifier(*$1.string, @1, *$3.string, $3.i, @3); + } + ; + type_specifier_no_prec : type_specifier_nonarray { $$ = $1; @@ -1461,6 +1335,10 @@ type_specifier_nonarray TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtInt, qual, @1); } + | UINT_TYPE { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtUInt, qual, @1); + } | BOOL_TYPE { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtBool, qual, @1); @@ -1510,29 +1388,126 @@ type_specifier_nonarray $$.setBasic(EbtInt, qual, @1); $$.setAggregate(4); } + | UVEC2 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtUInt, qual, @1); + $$.setAggregate(2); + } + | UVEC3 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtUInt, qual, @1); + $$.setAggregate(3); + } + | UVEC4 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtUInt, qual, @1); + $$.setAggregate(4); + } | MATRIX2 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtFloat, qual, @1); - $$.setAggregate(2, true); + $$.setMatrix(2, 2); } | MATRIX3 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtFloat, qual, @1); - $$.setAggregate(3, true); + $$.setMatrix(3, 3); } | MATRIX4 { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtFloat, qual, @1); - $$.setAggregate(4, true); + $$.setMatrix(4, 4); + } + | MATRIX2x3 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); + $$.setMatrix(2, 3); + } + | MATRIX3x2 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); + $$.setMatrix(3, 2); + } + | MATRIX2x4 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); + $$.setMatrix(2, 4); + } + | MATRIX4x2 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); + $$.setMatrix(4, 2); + } + | MATRIX3x4 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); + $$.setMatrix(3, 4); + } + | MATRIX4x3 { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtFloat, qual, @1); + $$.setMatrix(4, 3); } | SAMPLER2D { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtSampler2D, qual, @1); } + | SAMPLER3D { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler3D, qual, @1); + } | SAMPLERCUBE { TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; $$.setBasic(EbtSamplerCube, qual, @1); } + | SAMPLER2DARRAY { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler2DArray, qual, @1); + } + | ISAMPLER2D { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtISampler2D, qual, @1); + } + | ISAMPLER3D { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtISampler3D, qual, @1); + } + | ISAMPLERCUBE { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtISamplerCube, qual, @1); + } + | ISAMPLER2DARRAY { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtISampler2DArray, qual, @1); + } + | USAMPLER2D { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtUSampler2D, qual, @1); + } + | USAMPLER3D { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtUSampler3D, qual, @1); + } + | USAMPLERCUBE { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtUSamplerCube, qual, @1); + } + | USAMPLER2DARRAY { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtUSampler2DArray, qual, @1); + } + | SAMPLER2DSHADOW { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler2DShadow, qual, @1); + } + | SAMPLERCUBESHADOW { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSamplerCubeShadow, qual, @1); + } + | SAMPLER2DARRAYSHADOW { + TQualifier qual = context->symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary; + $$.setBasic(EbtSampler2DArrayShadow, qual, @1); + } | SAMPLER_EXTERNAL_OES { if (!context->supportsExtension("GL_OES_EGL_image_external")) { context->error(@1, "unsupported type", "samplerExternalOES"); @@ -1567,24 +1542,10 @@ type_specifier_nonarray struct_specifier : STRUCT identifier LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { - if (context->reservedErrorCheck(@2, *$2.string)) - context->recover(); - - TType* structure = new TType(new TStructure($2.string, $5)); - TVariable* userTypeDef = new TVariable($2.string, *structure, true); - if (! context->symbolTable.insert(*userTypeDef)) { - context->error(@2, "redefinition", $2.string->c_str(), "struct"); - context->recover(); - } - $$.setBasic(EbtStruct, EvqTemporary, @1); - $$.userDef = structure; - context->exitStructDeclaration(); + $$ = context->addStructure(@1, @2, $2.string, $5); } | STRUCT LEFT_BRACE { if (context->enterStructDeclaration(@2, *$2.string)) context->recover(); } struct_declaration_list RIGHT_BRACE { - TType* structure = new TType(new TStructure(NewPoolTString(""), $4)); - $$.setBasic(EbtStruct, EvqTemporary, @1); - $$.userDef = structure; - context->exitStructDeclaration(); + $$ = context->addStructure(@1, @$, NewPoolTString(""), $4); } ; @@ -1609,34 +1570,13 @@ struct_declaration_list struct_declaration : type_specifier struct_declarator_list SEMICOLON { - $$ = $2; - - if (context->voidErrorCheck(@1, (*$2)[0]->name(), $1)) { - context->recover(); - } - for (unsigned int i = 0; i < $$->size(); ++i) { - // - // Careful not to replace already known aspects of type, like array-ness - // - TType* type = (*$$)[i]->type(); - type->setBasicType($1.type); - type->setNominalSize($1.size); - type->setMatrix($1.matrix); - type->setPrecision($1.precision); - - // don't allow arrays of arrays - if (type->isArray()) { - if (context->arrayTypeErrorCheck(@1, $1)) - context->recover(); - } - if ($1.array) - type->setArraySize($1.arraySize); - if ($1.userDef) - type->setStruct($1.userDef->getStruct()); - - if (context->structNestingErrorCheck(@1, *(*$$)[i])) - context->recover(); - } + $$ = context->addStructDeclaratorList($1, $2); + } + | type_qualifier type_specifier struct_declarator_list SEMICOLON { + // ES3 Only, but errors should be handled elsewhere + $2.qualifier = $1.qualifier; + $2.layoutQualifier = $1.layoutQualifier; + $$ = context->addStructDeclaratorList($2, $3); } ; @@ -1656,19 +1596,19 @@ struct_declarator context->recover(); TType* type = new TType(EbtVoid, EbpUndefined); - $$ = new TField(type, $1.string); + $$ = new TField(type, $1.string, @1); } | identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { if (context->reservedErrorCheck(@1, *$1.string)) context->recover(); TType* type = new TType(EbtVoid, EbpUndefined); - int size = 0; + int size; if (context->arraySizeErrorCheck(@3, $3, size)) context->recover(); type->setArraySize(size); - $$ = new TField(type, $1.string); + $$ = new TField(type, $1.string, @1); } ; @@ -1902,7 +1842,7 @@ function_definition : function_prototype { TFunction* function = $1.function; - const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName()); + const TSymbol *builtIn = context->symbolTable.findBuiltIn(function->getMangledName(), context->shaderVersion); if (builtIn) { @@ -1910,7 +1850,7 @@ function_definition context->recover(); } - TFunction* prevDec = static_cast(context->symbolTable.find(function->getMangledName())); + TFunction* prevDec = static_cast(context->symbolTable.find(function->getMangledName(), context->shaderVersion)); // // Note: 'prevDec' could be 'function' if this is the first time we've seen function // as it would have just been put in the symbol table. Otherwise, we're looking up @@ -1961,7 +1901,7 @@ function_definition // // Insert the parameters with name in the symbol table. // - if (! context->symbolTable.insert(*variable)) { + if (! context->symbolTable.declare(variable)) { context->error(@1, "redefinition", variable->getName().c_str()); context->recover(); delete variable; @@ -1973,9 +1913,8 @@ function_definition paramNodes = context->intermediate.growAggregate( paramNodes, context->intermediate.addSymbol(variable->getUniqueId(), - variable->getName(), - variable->getType(), - @1), + variable->getName(), + variable->getType(), @1), @1); } else { paramNodes = context->intermediate.growAggregate(paramNodes, context->intermediate.addSymbol(0, "", *param.type, @1), @1); diff --git a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp index f2f918d77a..a6e7ab41a6 100644 --- a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp +++ b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp @@ -1,10 +1,14 @@ // -// Copyright (c) 2002-2010 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. // #include "compiler/translator/localintermediate.h" +#include "compiler/translator/SymbolTable.h" + +namespace +{ // // Two purposes: @@ -19,22 +23,40 @@ // Use this class to carry along data from node to node in // the traversal // -class TOutputTraverser : public TIntermTraverser { -public: - TOutputTraverser(TInfoSinkBase& i) : sink(i) { } +class TOutputTraverser : public TIntermTraverser +{ + public: + TOutputTraverser(TInfoSinkBase &i) + : sink(i) { } TInfoSinkBase& sink; -protected: - void visitSymbol(TIntermSymbol*); - void visitConstantUnion(TIntermConstantUnion*); - bool visitBinary(Visit visit, TIntermBinary*); - bool visitUnary(Visit visit, TIntermUnary*); - bool visitSelection(Visit visit, TIntermSelection*); - bool visitAggregate(Visit visit, TIntermAggregate*); - bool visitLoop(Visit visit, TIntermLoop*); - bool visitBranch(Visit visit, TIntermBranch*); + protected: + void visitSymbol(TIntermSymbol *); + void visitConstantUnion(TIntermConstantUnion *); + bool visitBinary(Visit visit, TIntermBinary *); + bool visitUnary(Visit visit, TIntermUnary *); + bool visitSelection(Visit visit, TIntermSelection *); + bool visitAggregate(Visit visit, TIntermAggregate *); + bool visitLoop(Visit visit, TIntermLoop *); + bool visitBranch(Visit visit, TIntermBranch *); }; +// +// Helper functions for printing, not part of traversing. +// +void OutputTreeText(TInfoSinkBase &sink, TIntermNode *node, const int depth) +{ + int i; + + sink.location(node->getLine()); + + for (i = 0; i < depth; ++i) + sink << " "; +} + +} // namespace anonymous + + TString TType::getCompleteString() const { TStringStream stream; @@ -43,29 +65,15 @@ TString TType::getCompleteString() const stream << getQualifierString() << " " << getPrecisionString() << " "; if (array) stream << "array[" << getArraySize() << "] of "; - if (matrix) - stream << static_cast(size) << "X" << static_cast(size) << " matrix of "; - else if (size > 1) - stream << static_cast(size) << "-component vector of "; + if (isMatrix()) + stream << getCols() << "X" << getRows() << " matrix of "; + else if (isVector()) + stream << getNominalSize() << "-component vector of "; stream << getBasicString(); return stream.str(); } -// -// Helper functions for printing, not part of traversing. -// - -void OutputTreeText(TInfoSinkBase& sink, TIntermNode* node, const int depth) -{ - int i; - - sink.location(node->getLine()); - - for (i = 0; i < depth; ++i) - sink << " "; -} - // // The rest of the file are the traversal functions. The last one // is the one that starts the traversal. @@ -75,57 +83,126 @@ void OutputTreeText(TInfoSinkBase& sink, TIntermNode* node, const int depth) // return false. // -void TOutputTraverser::visitSymbol(TIntermSymbol* node) +void TOutputTraverser::visitSymbol(TIntermSymbol *node) { - OutputTreeText(sink, node, depth); + OutputTreeText(sink, node, mDepth); sink << "'" << node->getSymbol() << "' "; sink << "(" << node->getCompleteString() << ")\n"; } -bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node) +bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) { TInfoSinkBase& out = sink; - OutputTreeText(out, node, depth); - - switch (node->getOp()) { - case EOpAssign: out << "move second child to first child"; break; - case EOpInitialize: out << "initialize first child with second child"; break; - case EOpAddAssign: out << "add second child into first child"; break; - case EOpSubAssign: out << "subtract second child into first child"; break; - case EOpMulAssign: out << "multiply second child into first child"; break; - case EOpVectorTimesMatrixAssign: out << "matrix mult second child into first child"; break; - case EOpVectorTimesScalarAssign: out << "vector scale second child into first child"; break; - case EOpMatrixTimesScalarAssign: out << "matrix scale second child into first child"; break; - case EOpMatrixTimesMatrixAssign: out << "matrix mult second child into first child"; break; - case EOpDivAssign: out << "divide second child into first child"; break; - case EOpIndexDirect: out << "direct index"; break; - case EOpIndexIndirect: out << "indirect index"; break; - case EOpIndexDirectStruct: out << "direct index for structure"; break; - case EOpVectorSwizzle: out << "vector swizzle"; break; - - case EOpAdd: out << "add"; break; - case EOpSub: out << "subtract"; break; - case EOpMul: out << "component-wise multiply"; break; - case EOpDiv: out << "divide"; break; - case EOpEqual: out << "Compare Equal"; break; - case EOpNotEqual: out << "Compare Not Equal"; break; - case EOpLessThan: out << "Compare Less Than"; break; - case EOpGreaterThan: out << "Compare Greater Than"; break; - case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; - case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; - - case EOpVectorTimesScalar: out << "vector-scale"; break; - case EOpVectorTimesMatrix: out << "vector-times-matrix"; break; - case EOpMatrixTimesVector: out << "matrix-times-vector"; break; - case EOpMatrixTimesScalar: out << "matrix-scale"; break; - case EOpMatrixTimesMatrix: out << "matrix-multiply"; break; - - case EOpLogicalOr: out << "logical-or"; break; - case EOpLogicalXor: out << "logical-xor"; break; - case EOpLogicalAnd: out << "logical-and"; break; - default: out << ""; + OutputTreeText(out, node, mDepth); + + switch (node->getOp()) + { + case EOpAssign: + out << "move second child to first child"; + break; + case EOpInitialize: + out << "initialize first child with second child"; + break; + case EOpAddAssign: + out << "add second child into first child"; + break; + case EOpSubAssign: + out << "subtract second child into first child"; + break; + case EOpMulAssign: + out << "multiply second child into first child"; + break; + case EOpVectorTimesMatrixAssign: + out << "matrix mult second child into first child"; + break; + case EOpVectorTimesScalarAssign: + out << "vector scale second child into first child"; + break; + case EOpMatrixTimesScalarAssign: + out << "matrix scale second child into first child"; + break; + case EOpMatrixTimesMatrixAssign: + out << "matrix mult second child into first child"; + break; + case EOpDivAssign: + out << "divide second child into first child"; + break; + case EOpIndexDirect: + out << "direct index"; + break; + case EOpIndexIndirect: + out << "indirect index"; + break; + case EOpIndexDirectStruct: + out << "direct index for structure"; + break; + case EOpIndexDirectInterfaceBlock: + out << "direct index for interface block"; + break; + case EOpVectorSwizzle: + out << "vector swizzle"; + break; + + case EOpAdd: + out << "add"; + break; + case EOpSub: + out << "subtract"; + break; + case EOpMul: + out << "component-wise multiply"; + break; + case EOpDiv: + out << "divide"; + break; + case EOpEqual: + out << "Compare Equal"; + break; + case EOpNotEqual: + out << "Compare Not Equal"; + break; + case EOpLessThan: + out << "Compare Less Than"; + break; + case EOpGreaterThan: + out << "Compare Greater Than"; + break; + case EOpLessThanEqual: + out << "Compare Less Than or Equal"; + break; + case EOpGreaterThanEqual: + out << "Compare Greater Than or Equal"; + break; + + case EOpVectorTimesScalar: + out << "vector-scale"; + break; + case EOpVectorTimesMatrix: + out << "vector-times-matrix"; + break; + case EOpMatrixTimesVector: + out << "matrix-times-vector"; + break; + case EOpMatrixTimesScalar: + out << "matrix-scale"; + break; + case EOpMatrixTimesMatrix: + out << "matrix-multiply"; + break; + + case EOpLogicalOr: + out << "logical-or"; + break; + case EOpLogicalXor: + out << "logical-xor"; + break; + case EOpLogicalAnd: + out << "logical-and"; + break; + default: + out << ""; } out << " (" << node->getCompleteString() << ")"; @@ -135,63 +212,57 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary* node) return true; } -bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node) +bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) { TInfoSinkBase& out = sink; - OutputTreeText(out, node, depth); - - switch (node->getOp()) { - case EOpNegative: out << "Negate value"; break; - case EOpVectorLogicalNot: - case EOpLogicalNot: out << "Negate conditional"; break; - - case EOpPostIncrement: out << "Post-Increment"; break; - case EOpPostDecrement: out << "Post-Decrement"; break; - case EOpPreIncrement: out << "Pre-Increment"; break; - case EOpPreDecrement: out << "Pre-Decrement"; break; - - case EOpConvIntToBool: out << "Convert int to bool"; break; - case EOpConvFloatToBool:out << "Convert float to bool";break; - case EOpConvBoolToFloat:out << "Convert bool to float";break; - case EOpConvIntToFloat: out << "Convert int to float"; break; - case EOpConvFloatToInt: out << "Convert float to int"; break; - case EOpConvBoolToInt: out << "Convert bool to int"; break; - - case EOpRadians: out << "radians"; break; - case EOpDegrees: out << "degrees"; break; - case EOpSin: out << "sine"; break; - case EOpCos: out << "cosine"; break; - case EOpTan: out << "tangent"; break; - case EOpAsin: out << "arc sine"; break; - case EOpAcos: out << "arc cosine"; break; - case EOpAtan: out << "arc tangent"; break; - - case EOpExp: out << "exp"; break; - case EOpLog: out << "log"; break; - case EOpExp2: out << "exp2"; break; - case EOpLog2: out << "log2"; break; - case EOpSqrt: out << "sqrt"; break; - case EOpInverseSqrt: out << "inverse sqrt"; break; - - case EOpAbs: out << "Absolute value"; break; - case EOpSign: out << "Sign"; break; - case EOpFloor: out << "Floor"; break; - case EOpCeil: out << "Ceiling"; break; - case EOpFract: out << "Fraction"; break; - - case EOpLength: out << "length"; break; - case EOpNormalize: out << "normalize"; break; - // case EOpDPdx: out << "dPdx"; break; - // case EOpDPdy: out << "dPdy"; break; - // case EOpFwidth: out << "fwidth"; break; - - case EOpAny: out << "any"; break; - case EOpAll: out << "all"; break; - - default: - out.prefix(EPrefixError); - out << "Bad unary op"; + OutputTreeText(out, node, mDepth); + + switch (node->getOp()) + { + case EOpNegative: out << "Negate value"; break; + case EOpVectorLogicalNot: + case EOpLogicalNot: out << "Negate conditional"; break; + + case EOpPostIncrement: out << "Post-Increment"; break; + case EOpPostDecrement: out << "Post-Decrement"; break; + case EOpPreIncrement: out << "Pre-Increment"; break; + case EOpPreDecrement: out << "Pre-Decrement"; break; + + case EOpRadians: out << "radians"; break; + case EOpDegrees: out << "degrees"; break; + case EOpSin: out << "sine"; break; + case EOpCos: out << "cosine"; break; + case EOpTan: out << "tangent"; break; + case EOpAsin: out << "arc sine"; break; + case EOpAcos: out << "arc cosine"; break; + case EOpAtan: out << "arc tangent"; break; + + case EOpExp: out << "exp"; break; + case EOpLog: out << "log"; break; + case EOpExp2: out << "exp2"; break; + case EOpLog2: out << "log2"; break; + case EOpSqrt: out << "sqrt"; break; + case EOpInverseSqrt: out << "inverse sqrt"; break; + + case EOpAbs: out << "Absolute value"; break; + case EOpSign: out << "Sign"; break; + case EOpFloor: out << "Floor"; break; + case EOpCeil: out << "Ceiling"; break; + case EOpFract: out << "Fraction"; break; + + case EOpLength: out << "length"; break; + case EOpNormalize: out << "normalize"; break; + // case EOpDPdx: out << "dPdx"; break; + // case EOpDPdy: out << "dPdy"; break; + // case EOpFwidth: out << "fwidth"; break; + + case EOpAny: out << "any"; break; + case EOpAll: out << "all"; break; + + default: + out.prefix(EPrefixError); + out << "Bad unary op"; } out << " (" << node->getCompleteString() << ")"; @@ -201,74 +272,80 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary* node) return true; } -bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node) +bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) { - TInfoSinkBase& out = sink; + TInfoSinkBase &out = sink; - if (node->getOp() == EOpNull) { + if (node->getOp() == EOpNull) + { out.prefix(EPrefixError); out << "node is still EOpNull!"; return true; } - OutputTreeText(out, node, depth); - - switch (node->getOp()) { - case EOpSequence: out << "Sequence\n"; return true; - case EOpComma: out << "Comma\n"; return true; - case EOpFunction: out << "Function Definition: " << node->getName(); break; - case EOpFunctionCall: out << "Function Call: " << node->getName(); break; - case EOpParameters: out << "Function Parameters: "; break; - - case EOpConstructFloat: out << "Construct float"; break; - case EOpConstructVec2: out << "Construct vec2"; break; - case EOpConstructVec3: out << "Construct vec3"; break; - case EOpConstructVec4: out << "Construct vec4"; break; - case EOpConstructBool: out << "Construct bool"; break; - case EOpConstructBVec2: out << "Construct bvec2"; break; - case EOpConstructBVec3: out << "Construct bvec3"; break; - case EOpConstructBVec4: out << "Construct bvec4"; break; - case EOpConstructInt: out << "Construct int"; break; - case EOpConstructIVec2: out << "Construct ivec2"; break; - case EOpConstructIVec3: out << "Construct ivec3"; break; - case EOpConstructIVec4: out << "Construct ivec4"; break; - case EOpConstructMat2: out << "Construct mat2"; break; - case EOpConstructMat3: out << "Construct mat3"; break; - case EOpConstructMat4: out << "Construct mat4"; break; - case EOpConstructStruct: out << "Construct structure"; break; - - case EOpLessThan: out << "Compare Less Than"; break; - case EOpGreaterThan: out << "Compare Greater Than"; break; - case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; - case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; - case EOpVectorEqual: out << "Equal"; break; - case EOpVectorNotEqual: out << "NotEqual"; break; - - case EOpMod: out << "mod"; break; - case EOpPow: out << "pow"; break; - - case EOpAtan: out << "arc tangent"; break; - - case EOpMin: out << "min"; break; - case EOpMax: out << "max"; break; - case EOpClamp: out << "clamp"; break; - case EOpMix: out << "mix"; break; - case EOpStep: out << "step"; break; - case EOpSmoothStep: out << "smoothstep"; break; - - case EOpDistance: out << "distance"; break; - case EOpDot: out << "dot-product"; break; - case EOpCross: out << "cross-product"; break; - case EOpFaceForward: out << "face-forward"; break; - case EOpReflect: out << "reflect"; break; - case EOpRefract: out << "refract"; break; - case EOpMul: out << "component-wise multiply"; break; - - case EOpDeclaration: out << "Declaration: "; break; - - default: - out.prefix(EPrefixError); - out << "Bad aggregation op"; + OutputTreeText(out, node, mDepth); + + switch (node->getOp()) + { + case EOpSequence: out << "Sequence\n"; return true; + case EOpComma: out << "Comma\n"; return true; + case EOpFunction: out << "Function Definition: " << node->getName(); break; + case EOpFunctionCall: out << "Function Call: " << node->getName(); break; + case EOpParameters: out << "Function Parameters: "; break; + + case EOpConstructFloat: out << "Construct float"; break; + case EOpConstructVec2: out << "Construct vec2"; break; + case EOpConstructVec3: out << "Construct vec3"; break; + case EOpConstructVec4: out << "Construct vec4"; break; + case EOpConstructBool: out << "Construct bool"; break; + case EOpConstructBVec2: out << "Construct bvec2"; break; + case EOpConstructBVec3: out << "Construct bvec3"; break; + case EOpConstructBVec4: out << "Construct bvec4"; break; + case EOpConstructInt: out << "Construct int"; break; + case EOpConstructIVec2: out << "Construct ivec2"; break; + case EOpConstructIVec3: out << "Construct ivec3"; break; + case EOpConstructIVec4: out << "Construct ivec4"; break; + case EOpConstructUInt: out << "Construct uint"; break; + case EOpConstructUVec2: out << "Construct uvec2"; break; + case EOpConstructUVec3: out << "Construct uvec3"; break; + case EOpConstructUVec4: out << "Construct uvec4"; break; + case EOpConstructMat2: out << "Construct mat2"; break; + case EOpConstructMat3: out << "Construct mat3"; break; + case EOpConstructMat4: out << "Construct mat4"; break; + case EOpConstructStruct: out << "Construct structure"; break; + + case EOpLessThan: out << "Compare Less Than"; break; + case EOpGreaterThan: out << "Compare Greater Than"; break; + case EOpLessThanEqual: out << "Compare Less Than or Equal"; break; + case EOpGreaterThanEqual: out << "Compare Greater Than or Equal"; break; + case EOpVectorEqual: out << "Equal"; break; + case EOpVectorNotEqual: out << "NotEqual"; break; + + case EOpMod: out << "mod"; break; + case EOpPow: out << "pow"; break; + + case EOpAtan: out << "arc tangent"; break; + + case EOpMin: out << "min"; break; + case EOpMax: out << "max"; break; + case EOpClamp: out << "clamp"; break; + case EOpMix: out << "mix"; break; + case EOpStep: out << "step"; break; + case EOpSmoothStep: out << "smoothstep"; break; + + case EOpDistance: out << "distance"; break; + case EOpDot: out << "dot-product"; break; + case EOpCross: out << "cross-product"; break; + case EOpFaceForward: out << "face-forward"; break; + case EOpReflect: out << "reflect"; break; + case EOpRefract: out << "refract"; break; + case EOpMul: out << "component-wise multiply"; break; + + case EOpDeclaration: out << "Declaration: "; break; + + default: + out.prefix(EPrefixError); + out << "Bad aggregation op"; } if (node->getOp() != EOpSequence && node->getOp() != EOpParameters) @@ -279,131 +356,156 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate* node) return true; } -bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection* node) +bool TOutputTraverser::visitSelection(Visit visit, TIntermSelection *node) { - TInfoSinkBase& out = sink; + TInfoSinkBase &out = sink; - OutputTreeText(out, node, depth); + OutputTreeText(out, node, mDepth); out << "Test condition and select"; out << " (" << node->getCompleteString() << ")\n"; - ++depth; + ++mDepth; - OutputTreeText(sink, node, depth); + OutputTreeText(sink, node, mDepth); out << "Condition\n"; node->getCondition()->traverse(this); - OutputTreeText(sink, node, depth); - if (node->getTrueBlock()) { + OutputTreeText(sink, node, mDepth); + if (node->getTrueBlock()) + { out << "true case\n"; node->getTrueBlock()->traverse(this); - } else + } + else + { out << "true case is null\n"; + } - if (node->getFalseBlock()) { - OutputTreeText(sink, node, depth); + if (node->getFalseBlock()) + { + OutputTreeText(sink, node, mDepth); out << "false case\n"; node->getFalseBlock()->traverse(this); } - --depth; + --mDepth; return false; } -void TOutputTraverser::visitConstantUnion(TIntermConstantUnion* node) +void TOutputTraverser::visitConstantUnion(TIntermConstantUnion *node) { - TInfoSinkBase& out = sink; + TInfoSinkBase &out = sink; size_t size = node->getType().getObjectSize(); - for (size_t i = 0; i < size; i++) { - OutputTreeText(out, node, depth); - switch (node->getUnionArrayPointer()[i].getType()) { - case EbtBool: - if (node->getUnionArrayPointer()[i].getBConst()) - out << "true"; - else - out << "false"; - - out << " (" << "const bool" << ")"; - out << "\n"; - break; - case EbtFloat: - out << node->getUnionArrayPointer()[i].getFConst(); - out << " (const float)\n"; - break; - case EbtInt: - out << node->getUnionArrayPointer()[i].getIConst(); - out << " (const int)\n"; - break; - default: - out.message(EPrefixInternalError, node->getLine(), "Unknown constant"); - break; + for (size_t i = 0; i < size; i++) + { + OutputTreeText(out, node, mDepth); + switch (node->getUnionArrayPointer()[i].getType()) + { + case EbtBool: + if (node->getUnionArrayPointer()[i].getBConst()) + out << "true"; + else + out << "false"; + + out << " (" << "const bool" << ")"; + out << "\n"; + break; + case EbtFloat: + out << node->getUnionArrayPointer()[i].getFConst(); + out << " (const float)\n"; + break; + case EbtInt: + out << node->getUnionArrayPointer()[i].getIConst(); + out << " (const int)\n"; + break; + case EbtUInt: + out << node->getUnionArrayPointer()[i].getUConst(); + out << " (const uint)\n"; + break; + default: + out.message(EPrefixInternalError, node->getLine(), "Unknown constant"); + break; } } } -bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop* node) +bool TOutputTraverser::visitLoop(Visit visit, TIntermLoop *node) { - TInfoSinkBase& out = sink; + TInfoSinkBase &out = sink; - OutputTreeText(out, node, depth); + OutputTreeText(out, node, mDepth); out << "Loop with condition "; if (node->getType() == ELoopDoWhile) out << "not "; out << "tested first\n"; - ++depth; + ++mDepth; - OutputTreeText(sink, node, depth); - if (node->getCondition()) { + OutputTreeText(sink, node, mDepth); + if (node->getCondition()) + { out << "Loop Condition\n"; node->getCondition()->traverse(this); - } else + } + else + { out << "No loop condition\n"; + } - OutputTreeText(sink, node, depth); - if (node->getBody()) { + OutputTreeText(sink, node, mDepth); + if (node->getBody()) + { out << "Loop Body\n"; node->getBody()->traverse(this); - } else + } + else + { out << "No loop body\n"; + } - if (node->getExpression()) { - OutputTreeText(sink, node, depth); + if (node->getExpression()) + { + OutputTreeText(sink, node, mDepth); out << "Loop Terminal Expression\n"; node->getExpression()->traverse(this); } - --depth; + --mDepth; return false; } -bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node) +bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node) { - TInfoSinkBase& out = sink; + TInfoSinkBase &out = sink; - OutputTreeText(out, node, depth); + OutputTreeText(out, node, mDepth); - switch (node->getFlowOp()) { - case EOpKill: out << "Branch: Kill"; break; - case EOpBreak: out << "Branch: Break"; break; - case EOpContinue: out << "Branch: Continue"; break; - case EOpReturn: out << "Branch: Return"; break; - default: out << "Branch: Unknown Branch"; break; + switch (node->getFlowOp()) + { + case EOpKill: out << "Branch: Kill"; break; + case EOpBreak: out << "Branch: Break"; break; + case EOpContinue: out << "Branch: Continue"; break; + case EOpReturn: out << "Branch: Return"; break; + default: out << "Branch: Unknown Branch"; break; } - if (node->getExpression()) { + if (node->getExpression()) + { out << " with expression\n"; - ++depth; + ++mDepth; node->getExpression()->traverse(this); - --depth; - } else + --mDepth; + } + else + { out << "\n"; + } return false; } @@ -413,12 +515,12 @@ bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch* node) // Individual functions can be initialized to 0 to skip processing of that // type of node. It's children will still be processed. // -void TIntermediate::outputTree(TIntermNode* root) +void TIntermediate::outputTree(TIntermNode *root) { - if (root == 0) + if (root == NULL) return; - TOutputTraverser it(infoSink.info); + TOutputTraverser it(mInfoSink.info); root->traverse(&it); } diff --git a/src/3rdparty/angle/src/compiler/translator/intermediate.h b/src/3rdparty/angle/src/compiler/translator/intermediate.h index 8f9fe23d3b..892f2849e0 100644 --- a/src/3rdparty/angle/src/compiler/translator/intermediate.h +++ b/src/3rdparty/angle/src/compiler/translator/intermediate.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2013 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. // @@ -8,17 +8,19 @@ // 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 +// Nodes in the tree are defined as a hierarchy of classes derived from // TIntermNode. Each is a node in a tree. There is no preset branching factor; // each node can have it's own type of list of children. // -#ifndef __INTERMEDIATE_H -#define __INTERMEDIATE_H +#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" @@ -26,10 +28,11 @@ // // Operators used by the high-level (parse tree) representation. // -enum TOperator { +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, + EOpFunctionCall, EOpFunction, // For function definition EOpParameters, // an aggregate listing the parameters to a function @@ -49,13 +52,6 @@ enum TOperator { EOpPreIncrement, EOpPreDecrement, - EOpConvIntToBool, - EOpConvFloatToBool, - EOpConvBoolToFloat, - EOpConvIntToFloat, - EOpConvFloatToInt, - EOpConvBoolToInt, - // // binary operations // @@ -86,6 +82,7 @@ enum TOperator { EOpIndexDirect, EOpIndexIndirect, EOpIndexDirectStruct, + EOpIndexDirectInterfaceBlock, EOpVectorSwizzle, @@ -155,6 +152,7 @@ enum TOperator { // EOpConstructInt, + EOpConstructUInt, EOpConstructBool, EOpConstructFloat, EOpConstructVec2, @@ -166,6 +164,9 @@ enum TOperator { EOpConstructIVec2, EOpConstructIVec3, EOpConstructIVec4, + EOpConstructUVec2, + EOpConstructUVec3, + EOpConstructUVec4, EOpConstructMat2, EOpConstructMat3, EOpConstructMat4, @@ -187,8 +188,6 @@ enum TOperator { EOpDivAssign }; -extern const char* getOperatorString(TOperator op); - class TIntermTraverser; class TIntermAggregate; class TIntermBinary; @@ -199,347 +198,454 @@ class TIntermTyped; class TIntermSymbol; class TIntermLoop; class TInfoSink; +class TIntermRaw; // // Base class for the tree nodes // -class TIntermNode { -public: +class TIntermNode +{ + public: POOL_ALLOCATOR_NEW_DELETE(); - TIntermNode() { + TIntermNode() + { // TODO: Move this to TSourceLoc constructor // after getting rid of TPublicType. - line.first_file = line.last_file = 0; - line.first_line = line.last_line = 0; + mLine.first_file = mLine.last_file = 0; + mLine.first_line = mLine.last_line = 0; } virtual ~TIntermNode() { } - const TSourceLoc& getLine() const { return line; } - void setLine(const TSourceLoc& l) { line = l; } + 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 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; -protected: - TSourceLoc line; + // 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; +struct TIntermNodePair +{ + TIntermNode *node1; + TIntermNode *node2; }; // // Intermediate class for nodes that have a type. // -class TIntermTyped : public TIntermNode { -public: - TIntermTyped(const TType& t) : type(t) { } - virtual TIntermTyped* getAsTyped() { return this; } +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) { type = t; } - const TType& getType() const { return type; } - TType* getTypePointer() { return &type; } - - TBasicType getBasicType() const { return type.getBasicType(); } - TQualifier getQualifier() const { return type.getQualifier(); } - TPrecision getPrecision() const { return type.getPrecision(); } - int getNominalSize() const { return type.getNominalSize(); } - - bool isMatrix() const { return type.isMatrix(); } - bool isArray() const { return type.isArray(); } - bool isVector() const { return type.isVector(); } - bool isScalar() const { return type.isScalar(); } - const char* getBasicString() const { return type.getBasicString(); } - const char* getQualifierString() const { return type.getQualifierString(); } - TString getCompleteString() const { return type.getCompleteString(); } - - int totalRegisterCount() const { return type.totalRegisterCount(); } - int elementRegisterCount() const { return type.elementRegisterCount(); } - int getArraySize() const { return type.getArraySize(); } - -protected: - TType type; + 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 { +enum TLoopType +{ ELoopFor, ELoopWhile, ELoopDoWhile }; -class TIntermLoop : public TIntermNode { -public: - TIntermLoop(TLoopType aType, - TIntermNode *aInit, TIntermTyped* aCond, TIntermTyped* aExpr, - TIntermNode* aBody) : - type(aType), - init(aInit), - cond(aCond), - expr(aExpr), - body(aBody), - unrollFlag(false) { } - - virtual TIntermLoop* getAsLoopNode() { return this; } - virtual void traverse(TIntermTraverser*); +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 type; } - TIntermNode* getInit() { return init; } - TIntermTyped* getCondition() { return cond; } - TIntermTyped* getExpression() { return expr; } - TIntermNode* getBody() { return body; } + 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) { unrollFlag = flag; } - bool getUnrollFlag() { return unrollFlag; } + void setUnrollFlag(bool flag) { mUnrollFlag = flag; } + bool getUnrollFlag() const { return mUnrollFlag; } -protected: - TLoopType type; - TIntermNode* init; // for-loop initialization - TIntermTyped* cond; // loop exit condition - TIntermTyped* expr; // for-loop expression - TIntermNode* body; // loop body + virtual void enqueueChildren(std::queue *nodeQueue) const; - bool unrollFlag; // Whether the loop should be unrolled or not. + 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) : - flowOp(op), - expression(e) { } +class TIntermBranch : public TIntermNode +{ + public: + TIntermBranch(TOperator op, TIntermTyped *e) + : mFlowOp(op), + mExpression(e) { } - virtual void traverse(TIntermTraverser*); + virtual void traverse(TIntermTraverser *); virtual bool replaceChildNode( TIntermNode *original, TIntermNode *replacement); - TOperator getFlowOp() { return flowOp; } - TIntermTyped* getExpression() { return expression; } + TOperator getFlowOp() { return mFlowOp; } + TIntermTyped* getExpression() { return mExpression; } + + virtual void enqueueChildren(std::queue *nodeQueue) const; protected: - TOperator flowOp; - TIntermTyped* expression; // non-zero except for "return exp;" statements + 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 i, const TString& sym, const TType& t) : - TIntermTyped(t), id(i) { symbol = sym; originalSymbol = sym; } +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 id; } - const TString& getSymbol() const { return symbol; } + 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 {} - void setId(int newId) { id = newId; } - void setSymbol(const TString& sym) { symbol = sym; } + protected: + int mId; + TString mSymbol; +}; - const TString& getOriginalSymbol() const { return originalSymbol; } +// 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; } - virtual void traverse(TIntermTraverser*); - virtual TIntermSymbol* getAsSymbolNode() { return this; } + 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: - int id; - TString symbol; - TString originalSymbol; + protected: + TString mRawText; }; -class TIntermConstantUnion : public TIntermTyped { -public: - TIntermConstantUnion(ConstantUnion *unionPointer, const TType& t) : TIntermTyped(t), unionArrayPointer(unionPointer) { } +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 unionArrayPointer; } - - int getIConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getIConst() : 0; } - float getFConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getFConst() : 0.0f; } - bool getBConst(size_t index) const { return unionArrayPointer ? unionArrayPointer[index].getBConst() : false; } + ConstantUnion *getUnionArrayPointer() const { return mUnionArrayPointer; } - virtual TIntermConstantUnion* getAsConstantUnion() { return this; } - virtual void traverse(TIntermTraverser*); + 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&); + TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &); -protected: - ConstantUnion *unionArrayPointer; + 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 op; } - void setOp(TOperator o) { op = o; } +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 o) : TIntermTyped(TType(EbtFloat, EbpUndefined)), op(o) {} - TIntermOperator(TOperator o, const TType& t) : TIntermTyped(t), op(o) {} - TOperator op; + 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 o) : TIntermOperator(o), addIndexClamp(false) {} +class TIntermBinary : public TIntermOperator +{ + public: + TIntermBinary(TOperator op) + : TIntermOperator(op), + mAddIndexClamp(false) {} - virtual TIntermBinary* getAsBinaryNode() { return this; } - virtual void traverse(TIntermTraverser*); + virtual TIntermBinary *getAsBinaryNode() { return this; } + virtual void traverse(TIntermTraverser *); virtual bool replaceChildNode( TIntermNode *original, TIntermNode *replacement); - virtual bool hasSideEffects() const { return (isAssignment() || left->hasSideEffects() || right->hasSideEffects()); } + virtual bool hasSideEffects() const + { + return isAssignment() || mLeft->hasSideEffects() || mRight->hasSideEffects(); + } - void setLeft(TIntermTyped* n) { left = n; } - void setRight(TIntermTyped* n) { right = n; } - TIntermTyped* getLeft() const { return left; } - TIntermTyped* getRight() const { return right; } - bool promote(TInfoSink&); + void 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() { addIndexClamp = true; } - bool getAddIndexClamp() { return addIndexClamp; } + void setAddIndexClamp() { mAddIndexClamp = true; } + bool getAddIndexClamp() { return mAddIndexClamp; } -protected: - TIntermTyped* left; - TIntermTyped* right; + 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 addIndexClamp; + bool mAddIndexClamp; }; // // Nodes for unary math operators. // -class TIntermUnary : public TIntermOperator { -public: - TIntermUnary(TOperator o, const TType& t) : TIntermOperator(o, t), operand(0), useEmulatedFunction(false) {} - TIntermUnary(TOperator o) : TIntermOperator(o), operand(0), useEmulatedFunction(false) {} - - virtual void traverse(TIntermTraverser*); - virtual TIntermUnary* getAsUnaryNode() { return this; } +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() || operand->hasSideEffects()); } + virtual bool hasSideEffects() const + { + return isAssignment() || mOperand->hasSideEffects(); + } - void setOperand(TIntermTyped* o) { operand = o; } - TIntermTyped* getOperand() { return operand; } - bool promote(TInfoSink&); + void setOperand(TIntermTyped *operand) { mOperand = operand; } + TIntermTyped *getOperand() { return mOperand; } + bool promote(TInfoSink &); - void setUseEmulatedFunction() { useEmulatedFunction = true; } - bool getUseEmulatedFunction() { return useEmulatedFunction; } + void setUseEmulatedFunction() { mUseEmulatedFunction = true; } + bool getUseEmulatedFunction() { return mUseEmulatedFunction; } -protected: - TIntermTyped* operand; + 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 useEmulatedFunction; + bool mUseEmulatedFunction; }; -typedef TVector TIntermSequence; +typedef TVector TIntermSequence; typedef TVector TQualifierList; // // Nodes that operate on an arbitrary sized set of children. // -class TIntermAggregate : public TIntermOperator { -public: - TIntermAggregate() : TIntermOperator(EOpNull), userDefined(false), useEmulatedFunction(false) { } - TIntermAggregate(TOperator o) : TIntermOperator(o), useEmulatedFunction(false) { } +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 TIntermAggregate *getAsAggregate() { return this; } + virtual void traverse(TIntermTraverser *); virtual bool replaceChildNode( TIntermNode *original, TIntermNode *replacement); // Conservatively assume function calls and other aggregate operators have side-effects virtual bool hasSideEffects() const { return true; } - TIntermSequence& getSequence() { return sequence; } + TIntermSequence *getSequence() { return &mSequence; } - void setName(const TString& n) { name = n; } - const TString& getName() const { return name; } + void setName(const TString &name) { mName = name; } + const TString &getName() const { return mName; } - void setUserDefined() { userDefined = true; } - bool isUserDefined() const { return userDefined; } + void setUserDefined() { mUserDefined = true; } + bool isUserDefined() const { return mUserDefined; } - void setOptimize(bool o) { optimize = o; } - bool getOptimize() { return optimize; } - void setDebug(bool d) { debug = d; } - bool getDebug() { return debug; } + void setOptimize(bool optimize) { mOptimize = optimize; } + bool getOptimize() const { return mOptimize; } + void setDebug(bool debug) { mDebug = debug; } + bool getDebug() const { return mDebug; } - void setUseEmulatedFunction() { useEmulatedFunction = true; } - bool getUseEmulatedFunction() { return useEmulatedFunction; } + void setUseEmulatedFunction() { mUseEmulatedFunction = true; } + bool getUseEmulatedFunction() { return mUseEmulatedFunction; } -protected: - TIntermAggregate(const TIntermAggregate&); // disallow copy constructor - TIntermAggregate& operator=(const TIntermAggregate&); // disallow assignment operator - TIntermSequence sequence; - TString name; - bool userDefined; // used for user defined function names + virtual void enqueueChildren(std::queue *nodeQueue) const; - bool optimize; - bool debug; + 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 useEmulatedFunction; + 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)), condition(cond), trueBlock(trueB), falseBlock(falseB) {} - TIntermSelection(TIntermTyped* cond, TIntermNode* trueB, TIntermNode* falseB, const TType& type) : - TIntermTyped(type), condition(cond), trueBlock(trueB), falseBlock(falseB) {} - - virtual void traverse(TIntermTraverser*); +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); @@ -547,15 +653,17 @@ public: virtual bool hasSideEffects() const { return true; } bool usesTernaryOperator() const { return getBasicType() != EbtVoid; } - TIntermNode* getCondition() const { return condition; } - TIntermNode* getTrueBlock() const { return trueBlock; } - TIntermNode* getFalseBlock() const { return falseBlock; } - TIntermSelection* getAsSelectionNode() { return this; } + 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* condition; - TIntermNode* trueBlock; - TIntermNode* falseBlock; + TIntermTyped *mCondition; + TIntermNode *mTrueBlock; + TIntermNode *mFalseBlock; }; enum Visit @@ -566,7 +674,7 @@ enum Visit }; // -// For traversing the tree. User should derive from this, +// For traversing the tree. User should derive from this, // put their traversal specific data in it, and then pass // it to a Traverse method. // @@ -575,44 +683,47 @@ enum Visit // class TIntermTraverser { -public: + public: POOL_ALLOCATOR_NEW_DELETE(); - TIntermTraverser(bool preVisit = true, bool inVisit = false, bool postVisit = false, bool rightToLeft = false) : - preVisit(preVisit), - inVisit(inVisit), - postVisit(postVisit), - rightToLeft(rightToLeft), - depth(0), - maxDepth(0) {} + // 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 visitConstantUnion(TIntermConstantUnion*) {} - virtual bool visitBinary(Visit visit, TIntermBinary*) {return true;} - virtual bool visitUnary(Visit visit, TIntermUnary*) {return true;} - virtual bool visitSelection(Visit visit, TIntermSelection*) {return true;} - virtual bool visitAggregate(Visit visit, TIntermAggregate*) {return true;} - virtual bool visitLoop(Visit visit, TIntermLoop*) {return true;} - virtual bool visitBranch(Visit visit, TIntermBranch*) {return true;} + 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 maxDepth;} + int getMaxDepth() const { return mMaxDepth; } void incrementDepth(TIntermNode *current) { - depth++; - maxDepth = std::max(maxDepth, depth); - path.push_back(current); + mDepth++; + mMaxDepth = std::max(mMaxDepth, mDepth); + mPath.push_back(current); } void decrementDepth() { - depth--; - path.pop_back(); + mDepth--; + mPath.pop_back(); } TIntermNode *getParentNode() { - return path.size() == 0 ? NULL : path.back(); + return mPath.size() == 0 ? NULL : mPath.back(); } // Return the original name if hash function pointer is NULL; @@ -624,12 +735,37 @@ public: const bool postVisit; const bool rightToLeft; -protected: - int depth; - int maxDepth; + protected: + int mDepth; + int mMaxDepth; // All the nodes from root to the current node's parent during traversing. - TVector path; + 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 // __INTERMEDIATE_H +#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/length_limits.h b/src/3rdparty/angle/src/compiler/translator/length_limits.h new file mode 100644 index 0000000000..df70ee5d84 --- /dev/null +++ b/src/3rdparty/angle/src/compiler/translator/length_limits.h @@ -0,0 +1,21 @@ +// +// Copyright (c) 2011-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// +// length_limits.h +// + +#if !defined(__LENGTH_LIMITS_H) +#define __LENGTH_LIMITS_H 1 + +#include "GLSLANG/ShaderLang.h" + +// These constants are factored out from the rest of the headers to +// make it easier to reference them from the compiler sources. + +size_t GetGlobalMaxTokenSize(ShShaderSpec spec); + +#endif // !(defined(__LENGTH_LIMITS_H) diff --git a/src/3rdparty/angle/src/compiler/translator/localintermediate.h b/src/3rdparty/angle/src/compiler/translator/localintermediate.h index b582e02f5d..0809bbd362 100644 --- a/src/3rdparty/angle/src/compiler/translator/localintermediate.h +++ b/src/3rdparty/angle/src/compiler/translator/localintermediate.h @@ -1,17 +1,16 @@ // -// Copyright (c) 2002-2010 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. // -#ifndef _LOCAL_INTERMEDIATE_INCLUDED_ -#define _LOCAL_INTERMEDIATE_INCLUDED_ +#ifndef COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ +#define COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ -#include "GLSLANG/ShaderLang.h" #include "compiler/translator/intermediate.h" -#include "compiler/translator/SymbolTable.h" -struct TVectorFields { +struct TVectorFields +{ int offsets[4]; int num; }; @@ -20,38 +19,49 @@ struct TVectorFields { // Set of helper functions to help parse and build the tree. // class TInfoSink; -class TIntermediate { -public: +class TIntermediate +{ + public: POOL_ALLOCATOR_NEW_DELETE(); - TIntermediate(TInfoSink& i) : infoSink(i) { } - - TIntermSymbol* addSymbol(int Id, const TString&, const TType&, const TSourceLoc&); - TIntermTyped* addConversion(TOperator, const TType&, TIntermTyped*); - TIntermTyped* addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&, TSymbolTable&); - TIntermTyped* addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); - TIntermTyped* addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc&); - TIntermTyped* addUnaryMath(TOperator op, TIntermNode* child, const TSourceLoc&, TSymbolTable&); - TIntermAggregate* growAggregate(TIntermNode* left, TIntermNode* right, const TSourceLoc&); - TIntermAggregate* makeAggregate(TIntermNode* node, const TSourceLoc&); - TIntermAggregate* setAggregateOperator(TIntermNode*, TOperator, const TSourceLoc&); - TIntermNode* addSelection(TIntermTyped* cond, TIntermNodePair code, const TSourceLoc&); - TIntermTyped* addSelection(TIntermTyped* cond, TIntermTyped* trueBlock, TIntermTyped* falseBlock, const TSourceLoc&); - TIntermTyped* addComma(TIntermTyped* left, TIntermTyped* right, const TSourceLoc&); - TIntermConstantUnion* addConstantUnion(ConstantUnion*, const TType&, const TSourceLoc&); - TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) ; - bool parseConstTree(const TSourceLoc&, TIntermNode*, ConstantUnion*, TOperator, TSymbolTable&, TType, bool singleConstantParam = false); - TIntermNode* addLoop(TLoopType, TIntermNode*, TIntermTyped*, TIntermTyped*, TIntermNode*, const TSourceLoc&); - TIntermBranch* addBranch(TOperator, const TSourceLoc&); - TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&); - TIntermTyped* addSwizzle(TVectorFields&, const TSourceLoc&); - bool postProcess(TIntermNode*); - void remove(TIntermNode*); - void outputTree(TIntermNode*); - -private: - void operator=(TIntermediate&); // prevent assignments - - TInfoSink& infoSink; + 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 // _LOCAL_INTERMEDIATE_INCLUDED_ +#endif // COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_ diff --git a/src/3rdparty/angle/src/compiler/translator/osinclude.h b/src/3rdparty/angle/src/compiler/translator/osinclude.h deleted file mode 100644 index cccfa6355c..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/osinclude.h +++ /dev/null @@ -1,64 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#ifndef __OSINCLUDE_H -#define __OSINCLUDE_H - -// -// This file contains contains os-specific datatypes and -// declares any os-specific functions. -// - -#if defined(_WIN32) || defined(_WIN64) -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) -#define ANGLE_OS_WINRT -#else -#define ANGLE_OS_WIN -#endif -#elif defined(__APPLE__) || defined(__linux__) || \ - defined(__FreeBSD__) || defined(__OpenBSD__) || \ - defined(__NetBSD__) || defined(__DragonFly__) || \ - defined(__sun) || defined(ANDROID) || \ - defined(__GLIBC__) || defined(__GNU__) || \ - defined(__QNX__) -#define ANGLE_OS_POSIX -#else -#error Unsupported platform. -#endif - -#if defined(ANGLE_OS_WIN) || defined(ANGLE_OS_WINRT) -#define STRICT -#define VC_EXTRALEAN 1 -#include -#elif defined(ANGLE_OS_POSIX) -#include -#include -#include -#endif // ANGLE_OS_WIN - - -#include "compiler/translator/compilerdebug.h" - -// -// Thread Local Storage Operations -// -#if defined(ANGLE_OS_WIN) -typedef DWORD OS_TLSIndex; -#define OS_INVALID_TLS_INDEX (TLS_OUT_OF_INDEXES) -#elif defined(ANGLE_OS_WINRT) -typedef size_t OS_TLSIndex; -#define OS_INVALID_TLS_INDEX ((DWORD)0xFFFFFF) -#elif defined(ANGLE_OS_POSIX) -typedef pthread_key_t OS_TLSIndex; -#define OS_INVALID_TLS_INDEX (static_cast(-1)) -#endif // ANGLE_OS_WIN - -OS_TLSIndex OS_AllocTLSIndex(); -void *OS_GetTLSValue(OS_TLSIndex nIndex); -bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue); -bool OS_FreeTLSIndex(OS_TLSIndex nIndex); - -#endif // __OSINCLUDE_H diff --git a/src/3rdparty/angle/src/compiler/translator/ossource_posix.cpp b/src/3rdparty/angle/src/compiler/translator/ossource_posix.cpp deleted file mode 100644 index d4bba4c70e..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ossource_posix.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// -// This file contains the posix specific functions -// -#include "compiler/translator/osinclude.h" - -#if !defined(ANGLE_OS_POSIX) -#error Trying to build a posix specific file in a non-posix build. -#endif - -// -// Thread Local Storage Operations -// -OS_TLSIndex OS_AllocTLSIndex() -{ - pthread_key_t pPoolIndex; - - // - // Create global pool key. - // - if ((pthread_key_create(&pPoolIndex, NULL)) != 0) { - assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage"); - return false; - } - else { - return pPoolIndex; - } -} - - -void *OS_GetTLSValue(OS_TLSIndex nIndex) -{ - ASSERT(nIndex != OS_INVALID_TLS_INDEX); - - return pthread_getspecific(nIndex); -} - - -bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - if (pthread_setspecific(nIndex, lpvValue) == 0) - return true; - else - return false; -} - - -bool OS_FreeTLSIndex(OS_TLSIndex nIndex) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - // - // Delete the global pool key. - // - if (pthread_key_delete(nIndex) == 0) - return true; - else - return false; -} diff --git a/src/3rdparty/angle/src/compiler/translator/ossource_win.cpp b/src/3rdparty/angle/src/compiler/translator/ossource_win.cpp deleted file mode 100644 index abd8bc7833..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ossource_win.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/osinclude.h" -// -// This file contains contains the window's specific functions -// - -#if !defined(ANGLE_OS_WIN) -#error Trying to build a windows specific file in a non windows build. -#endif - - -// -// Thread Local Storage Operations -// -OS_TLSIndex OS_AllocTLSIndex() -{ - DWORD dwIndex = TlsAlloc(); - if (dwIndex == TLS_OUT_OF_INDEXES) { - assert(0 && "OS_AllocTLSIndex(): Unable to allocate Thread Local Storage"); - return OS_INVALID_TLS_INDEX; - } - - return dwIndex; -} - - -void *OS_GetTLSValue(OS_TLSIndex nIndex) -{ - ASSERT(nIndex != OS_INVALID_TLS_INDEX); - - return TlsGetValue(nIndex); -} - - -bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - if (TlsSetValue(nIndex, lpvValue)) - return true; - else - return false; -} - - -bool OS_FreeTLSIndex(OS_TLSIndex nIndex) -{ - if (nIndex == OS_INVALID_TLS_INDEX) { - assert(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - if (TlsFree(nIndex)) - return true; - else - return false; -} diff --git a/src/3rdparty/angle/src/compiler/translator/ossource_winrt.cpp b/src/3rdparty/angle/src/compiler/translator/ossource_winrt.cpp deleted file mode 100644 index bb061ca85d..0000000000 --- a/src/3rdparty/angle/src/compiler/translator/ossource_winrt.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -#include "compiler/translator/osinclude.h" -// -// This file contains contains Windows Runtime specific functions -// - -#if !defined(ANGLE_OS_WINRT) -#error Trying to build a WinRT specific file in a non-WinRT build. -#endif - -#include - - -// -// Thread Local Storage Operations -// -__declspec(thread) std::vector *tls = nullptr; -__declspec(thread) std::vector *freeIndices = nullptr; - -OS_TLSIndex OS_AllocTLSIndex() -{ - if (!tls) - tls = new std::vector; - - if (freeIndices && !freeIndices->empty()) { - OS_TLSIndex index = freeIndices->back(); - freeIndices->pop_back(); - return index; - } else { - tls->push_back(nullptr); - return tls->size() - 1; - } -} - - -void *OS_GetTLSValue(OS_TLSIndex nIndex) -{ - ASSERT(nIndex != OS_INVALID_TLS_INDEX); - ASSERT(tls); - - return tls->at(nIndex); -} - - -bool OS_SetTLSValue(OS_TLSIndex nIndex, void *lpvValue) -{ - if (!tls || nIndex >= tls->size() || nIndex == OS_INVALID_TLS_INDEX) { - ASSERT(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - tls->at(nIndex) = lpvValue; - return true; -} - - -bool OS_FreeTLSIndex(OS_TLSIndex nIndex) -{ - if (!tls || nIndex >= tls->size() || nIndex == OS_INVALID_TLS_INDEX) { - ASSERT(0 && "OS_SetTLSValue(): Invalid TLS Index"); - return false; - } - - if (!freeIndices) - freeIndices = new std::vector; - - freeIndices->push_back(nIndex); - - return true; -} diff --git a/src/3rdparty/angle/src/compiler/translator/parseConst.cpp b/src/3rdparty/angle/src/compiler/translator/parseConst.cpp index a59f0be9d8..1897ed151c 100644 --- a/src/3rdparty/angle/src/compiler/translator/parseConst.cpp +++ b/src/3rdparty/angle/src/compiler/translator/parseConst.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 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. // @@ -7,47 +7,50 @@ #include "compiler/translator/ParseContext.h" // -// Use this class to carry along data from node to node in +// Use this class to carry along data from node to node in // the traversal // -class TConstTraverser : public TIntermTraverser { -public: - TConstTraverser(ConstantUnion* cUnion, bool singleConstParam, TOperator constructType, TInfoSink& sink, TSymbolTable& symTable, TType& t) +class TConstTraverser : public TIntermTraverser +{ + public: + TConstTraverser(ConstantUnion *cUnion, bool singleConstParam, + TOperator constructType, TInfoSink &sink, TType &t) : error(false), - index(0), - unionArray(cUnion), - type(t), - constructorType(constructType), - singleConstantParam(singleConstParam), - infoSink(sink), - symbolTable(symTable), - size(0), - isMatrix(false), - matrixSize(0) { + mIndex(0), + mUnionArray(cUnion), + mType(t), + mConstructorType(constructType), + mSingleConstantParam(singleConstParam), + mInfoSink(sink), + mSize(0), + mIsDiagonalMatrixInit(false), + mMatrixCols(0), + mMatrixRows(0) + { } bool error; -protected: - void visitSymbol(TIntermSymbol*); - void visitConstantUnion(TIntermConstantUnion*); - bool visitBinary(Visit visit, TIntermBinary*); - bool visitUnary(Visit visit, TIntermUnary*); - bool visitSelection(Visit visit, TIntermSelection*); - bool visitAggregate(Visit visit, TIntermAggregate*); - bool visitLoop(Visit visit, TIntermLoop*); - bool visitBranch(Visit visit, TIntermBranch*); - - size_t index; - ConstantUnion *unionArray; - TType type; - TOperator constructorType; - bool singleConstantParam; - TInfoSink& infoSink; - TSymbolTable& symbolTable; - size_t size; // size of the constructor ( 4 for vec4) - bool isMatrix; - size_t matrixSize; // dimension of the matrix (nominal size and not the instance size) + protected: + void visitSymbol(TIntermSymbol *); + void visitConstantUnion(TIntermConstantUnion *); + bool visitBinary(Visit visit, TIntermBinary *); + bool visitUnary(Visit visit, TIntermUnary *); + bool visitSelection(Visit visit, TIntermSelection *); + bool visitAggregate(Visit visit, TIntermAggregate *); + bool visitLoop(Visit visit, TIntermLoop *); + bool visitBranch(Visit visit, TIntermBranch *); + + size_t mIndex; + ConstantUnion *mUnionArray; + TType mType; + TOperator mConstructorType; + bool mSingleConstantParam; + TInfoSink &mInfoSink; + size_t mSize; // size of the constructor ( 4 for vec4) + bool mIsDiagonalMatrixInit; + int mMatrixCols; // columns of the matrix + int mMatrixRows; // rows of the matrix }; // @@ -58,169 +61,182 @@ protected: // continue on to children. If you process children yourself, // return false. // - -void TConstTraverser::visitSymbol(TIntermSymbol* node) +void TConstTraverser::visitSymbol(TIntermSymbol *node) { - infoSink.info.message(EPrefixInternalError, node->getLine(), "Symbol Node found in constant constructor"); + mInfoSink.info.message(EPrefixInternalError, node->getLine(), + "Symbol Node found in constant constructor"); return; - } -bool TConstTraverser::visitBinary(Visit visit, TIntermBinary* node) +bool TConstTraverser::visitBinary(Visit visit, TIntermBinary *node) { TQualifier qualifier = node->getType().getQualifier(); - - if (qualifier != EvqConst) { + + if (qualifier != EvqConst) + { TString buf; buf.append("'constructor' : assigning non-constant to "); - buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); + buf.append(mType.getCompleteString()); + mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); error = true; - return false; + return false; } - infoSink.info.message(EPrefixInternalError, node->getLine(), "Binary Node found in constant constructor"); - + mInfoSink.info.message(EPrefixInternalError, node->getLine(), + "Binary Node found in constant constructor"); return false; } -bool TConstTraverser::visitUnary(Visit visit, TIntermUnary* node) +bool TConstTraverser::visitUnary(Visit visit, TIntermUnary *node) { TString buf; buf.append("'constructor' : assigning non-constant to "); - buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); + buf.append(mType.getCompleteString()); + mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); error = true; - return false; + return false; } -bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate* node) +bool TConstTraverser::visitAggregate(Visit visit, TIntermAggregate *node) { - if (!node->isConstructor() && node->getOp() != EOpComma) { + if (!node->isConstructor() && node->getOp() != EOpComma) + { TString buf; buf.append("'constructor' : assigning non-constant to "); - buf.append(type.getCompleteString()); - infoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); + buf.append(mType.getCompleteString()); + mInfoSink.info.message(EPrefixError, node->getLine(), buf.c_str()); error = true; - return false; + return false; } - if (node->getSequence().size() == 0) { + if (node->getSequence()->size() == 0) + { error = true; return false; } - bool flag = node->getSequence().size() == 1 && node->getSequence()[0]->getAsTyped()->getAsConstantUnion(); - if (flag) + bool flag = node->getSequence()->size() == 1 && + (*node->getSequence())[0]->getAsTyped()->getAsConstantUnion(); + if (flag) { - singleConstantParam = true; - constructorType = node->getOp(); - size = node->getType().getObjectSize(); - - if (node->getType().isMatrix()) { - isMatrix = true; - matrixSize = node->getType().getNominalSize(); + mSingleConstantParam = true; + mConstructorType = node->getOp(); + mSize = node->getType().getObjectSize(); + + if (node->getType().isMatrix()) + { + mIsDiagonalMatrixInit = true; + mMatrixCols = node->getType().getCols(); + mMatrixRows = node->getType().getRows(); } - } - - for (TIntermSequence::iterator p = node->getSequence().begin(); - p != node->getSequence().end(); p++) { + } + for (TIntermSequence::iterator p = node->getSequence()->begin(); + p != node->getSequence()->end(); p++) + { if (node->getOp() == EOpComma) - index = 0; - + mIndex = 0; (*p)->traverse(this); - } - if (flag) + } + if (flag) { - singleConstantParam = false; - constructorType = EOpNull; - size = 0; - isMatrix = false; - matrixSize = 0; + mSingleConstantParam = false; + mConstructorType = EOpNull; + mSize = 0; + mIsDiagonalMatrixInit = false; + mMatrixCols = 0; + mMatrixRows = 0; } return false; } -bool TConstTraverser::visitSelection(Visit visit, TIntermSelection* node) +bool TConstTraverser::visitSelection(Visit visit, TIntermSelection *node) { - infoSink.info.message(EPrefixInternalError, node->getLine(), "Selection Node found in constant constructor"); + mInfoSink.info.message(EPrefixInternalError, node->getLine(), + "Selection Node found in constant constructor"); error = true; return false; } -void TConstTraverser::visitConstantUnion(TIntermConstantUnion* node) +void TConstTraverser::visitConstantUnion(TIntermConstantUnion *node) { if (!node->getUnionArrayPointer()) { // The constant was not initialized, this should already have been logged - assert(infoSink.info.size() != 0); + ASSERT(mInfoSink.info.size() != 0); return; } - ConstantUnion* leftUnionArray = unionArray; - size_t instanceSize = type.getObjectSize(); + ConstantUnion *leftUnionArray = mUnionArray; + size_t instanceSize = mType.getObjectSize(); + TBasicType basicType = mType.getBasicType(); - if (index >= instanceSize) + if (mIndex >= instanceSize) return; - if (!singleConstantParam) { - size_t size = node->getType().getObjectSize(); - + if (!mSingleConstantParam) + { + size_t objectSize = node->getType().getObjectSize(); ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); - for (size_t i = 0; i < size; i++) { - if (index >= instanceSize) + for (size_t i=0; i < objectSize; i++) + { + if (mIndex >= instanceSize) return; - leftUnionArray[index] = rightUnionArray[i]; - - (index)++; + leftUnionArray[mIndex].cast(basicType, rightUnionArray[i]); + mIndex++; } - } else { - size_t totalSize = index + size; + } + else + { + size_t totalSize = mIndex + mSize; ConstantUnion *rightUnionArray = node->getUnionArrayPointer(); - if (!isMatrix) { - size_t count = 0; - for (size_t i = index; i < totalSize; i++) { + if (!mIsDiagonalMatrixInit) + { + int count = 0; + for (size_t i = mIndex; i < totalSize; i++) + { if (i >= instanceSize) return; - - leftUnionArray[i] = rightUnionArray[count]; - - (index)++; - + leftUnionArray[i].cast(basicType, rightUnionArray[count]); + mIndex++; if (node->getType().getObjectSize() > 1) count++; } - } else { // for matrix constructors - size_t count = 0; - size_t element = index; - for (size_t i = index; i < totalSize; i++) { - if (i >= instanceSize) - return; - if (element - i == 0 || (i - element) % (matrixSize + 1) == 0 ) - leftUnionArray[i] = rightUnionArray[count]; - else - leftUnionArray[i].setFConst(0.0f); - - (index)++; - - if (node->getType().getObjectSize() > 1) - count++; + } + else + { + // for matrix diagonal constructors from a single scalar + for (int i = 0, col = 0; col < mMatrixCols; col++) + { + for (int row = 0; row < mMatrixRows; row++, i++) + { + if (col == row) + { + leftUnionArray[i].cast(basicType, rightUnionArray[0]); + } + else + { + leftUnionArray[i].setFConst(0.0f); + } + mIndex++; + } } } } } -bool TConstTraverser::visitLoop(Visit visit, TIntermLoop* node) +bool TConstTraverser::visitLoop(Visit visit, TIntermLoop *node) { - infoSink.info.message(EPrefixInternalError, node->getLine(), "Loop Node found in constant constructor"); + mInfoSink.info.message(EPrefixInternalError, node->getLine(), + "Loop Node found in constant constructor"); error = true; return false; } -bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node) +bool TConstTraverser::visitBranch(Visit visit, TIntermBranch *node) { - infoSink.info.message(EPrefixInternalError, node->getLine(), "Branch Node found in constant constructor"); + mInfoSink.info.message(EPrefixInternalError, node->getLine(), + "Branch Node found in constant constructor"); error = true; return false; } @@ -230,12 +246,15 @@ bool TConstTraverser::visitBranch(Visit visit, TIntermBranch* node) // Individual functions can be initialized to 0 to skip processing of that // type of node. It's children will still be processed. // -bool TIntermediate::parseConstTree(const TSourceLoc& line, TIntermNode* root, ConstantUnion* unionArray, TOperator constructorType, TSymbolTable& symbolTable, TType t, bool singleConstantParam) +bool TIntermediate::parseConstTree( + const TSourceLoc &line, TIntermNode *root, ConstantUnion *unionArray, + TOperator constructorType, TType t, bool singleConstantParam) { if (root == 0) return false; - TConstTraverser it(unionArray, singleConstantParam, constructorType, infoSink, symbolTable, t); + TConstTraverser it(unionArray, singleConstantParam, constructorType, + mInfoSink, t); root->traverse(&it); if (it.error) diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp index a9f3f49ef3..48d44c72d1 100644 --- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp @@ -31,6 +31,15 @@ RestrictFragmentShaderTiming::RestrictFragmentShaderTiming(TInfoSinkBase& sink) mSamplingOps.insert("texture2DRect(1;vf2;"); mSamplingOps.insert("texture2DRectProj(1;vf3;"); mSamplingOps.insert("texture2DRectProj(1;vf4;"); + // Sampling ops provided by EXT_shader_texture_lod. + mSamplingOps.insert("texture2DLodEXT(1;vf2;f1;"); + mSamplingOps.insert("texture2DProjLodEXT(1;vf3;f1;"); + mSamplingOps.insert("texture2DProjLodEXT(1;vf4;f1;"); + mSamplingOps.insert("textureCubeLodEXT(1;vf4;f1;"); + mSamplingOps.insert("texture2DGradEXT(1;vf2;vf2;vf2;"); + mSamplingOps.insert("texture2DProjGradEXT(1;vf3;vf2;vf2;"); + mSamplingOps.insert("texture2DProjGradEXT(1;vf4;vf2;vf2;"); + mSamplingOps.insert("textureCubeGradEXT(1;vf3;vf3;vf3;"); } // FIXME(mvujovic): We do not know if the execution time of built-in operations like sin, pow, etc. diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h index 323cb62d8a..e77d8c21cb 100644 --- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h @@ -7,8 +7,6 @@ #ifndef COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ #define COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_ -#include "GLSLANG/ShaderLang.h" - #include "compiler/translator/intermediate.h" #include "compiler/translator/depgraph/DependencyGraph.h" diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp index ee78c35450..7c1208a298 100644 --- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.cpp @@ -12,6 +12,6 @@ void RestrictVertexShaderTiming::visitSymbol(TIntermSymbol* node) ++mNumErrors; mSink.message(EPrefixError, node->getLine(), - "Samplers are not permitted in vertex shaders"); + "Samplers are not permitted in vertex shaders.\n"); } } diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h index 5f0dd3197a..d461fbdbfe 100644 --- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h +++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h @@ -7,8 +7,6 @@ #ifndef COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ #define COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_ -#include "GLSLANG/ShaderLang.h" - #include "compiler/translator/intermediate.h" #include "compiler/translator/InfoSink.h" diff --git a/src/3rdparty/angle/src/compiler/translator/util.cpp b/src/3rdparty/angle/src/compiler/translator/util.cpp index 077bdcc48b..561d4e007c 100644 --- a/src/3rdparty/angle/src/compiler/translator/util.cpp +++ b/src/3rdparty/angle/src/compiler/translator/util.cpp @@ -9,6 +9,8 @@ #include #include "compiler/preprocessor/numeric_lex.h" +#include "common/shadervars.h" +#include "common/utilities.h" bool atof_clamp(const char *str, float *value) { @@ -26,3 +28,329 @@ bool atoi_clamp(const char *str, int *value) return success; } +namespace sh +{ + +GLenum GLVariableType(const TType &type) +{ + if (type.getBasicType() == EbtFloat) + { + if (type.isScalar()) + { + return GL_FLOAT; + } + else if (type.isVector()) + { + switch (type.getNominalSize()) + { + case 2: return GL_FLOAT_VEC2; + case 3: return GL_FLOAT_VEC3; + case 4: return GL_FLOAT_VEC4; + default: UNREACHABLE(); + } + } + else if (type.isMatrix()) + { + switch (type.getCols()) + { + case 2: + switch (type.getRows()) + { + case 2: return GL_FLOAT_MAT2; + case 3: return GL_FLOAT_MAT2x3; + case 4: return GL_FLOAT_MAT2x4; + default: UNREACHABLE(); + } + + case 3: + switch (type.getRows()) + { + case 2: return GL_FLOAT_MAT3x2; + case 3: return GL_FLOAT_MAT3; + case 4: return GL_FLOAT_MAT3x4; + default: UNREACHABLE(); + } + + case 4: + switch (type.getRows()) + { + case 2: return GL_FLOAT_MAT4x2; + case 3: return GL_FLOAT_MAT4x3; + case 4: return GL_FLOAT_MAT4; + default: UNREACHABLE(); + } + + default: UNREACHABLE(); + } + } + else UNREACHABLE(); + } + else if (type.getBasicType() == EbtInt) + { + if (type.isScalar()) + { + return GL_INT; + } + else if (type.isVector()) + { + switch (type.getNominalSize()) + { + case 2: return GL_INT_VEC2; + case 3: return GL_INT_VEC3; + case 4: return GL_INT_VEC4; + default: UNREACHABLE(); + } + } + else UNREACHABLE(); + } + else if (type.getBasicType() == EbtUInt) + { + if (type.isScalar()) + { + return GL_UNSIGNED_INT; + } + else if (type.isVector()) + { + switch (type.getNominalSize()) + { + case 2: return GL_UNSIGNED_INT_VEC2; + case 3: return GL_UNSIGNED_INT_VEC3; + case 4: return GL_UNSIGNED_INT_VEC4; + default: UNREACHABLE(); + } + } + else UNREACHABLE(); + } + else if (type.getBasicType() == EbtBool) + { + if (type.isScalar()) + { + return GL_BOOL; + } + else if (type.isVector()) + { + switch (type.getNominalSize()) + { + case 2: return GL_BOOL_VEC2; + case 3: return GL_BOOL_VEC3; + case 4: return GL_BOOL_VEC4; + default: UNREACHABLE(); + } + } + else UNREACHABLE(); + } + + switch (type.getBasicType()) + { + case EbtSampler2D: return GL_SAMPLER_2D; + case EbtSampler3D: return GL_SAMPLER_3D; + case EbtSamplerCube: return GL_SAMPLER_CUBE; + case EbtSamplerExternalOES: return GL_SAMPLER_EXTERNAL_OES; + case EbtSampler2DRect: return GL_SAMPLER_2D_RECT_ARB; + case EbtSampler2DArray: return GL_SAMPLER_2D_ARRAY; + case EbtISampler2D: return GL_INT_SAMPLER_2D; + case EbtISampler3D: return GL_INT_SAMPLER_3D; + case EbtISamplerCube: return GL_INT_SAMPLER_CUBE; + case EbtISampler2DArray: return GL_INT_SAMPLER_2D_ARRAY; + case EbtUSampler2D: return GL_UNSIGNED_INT_SAMPLER_2D; + case EbtUSampler3D: return GL_UNSIGNED_INT_SAMPLER_3D; + case EbtUSamplerCube: return GL_UNSIGNED_INT_SAMPLER_CUBE; + case EbtUSampler2DArray: return GL_UNSIGNED_INT_SAMPLER_2D_ARRAY; + case EbtSampler2DShadow: return GL_SAMPLER_2D_SHADOW; + case EbtSamplerCubeShadow: return GL_SAMPLER_CUBE_SHADOW; + case EbtSampler2DArrayShadow: return GL_SAMPLER_2D_ARRAY_SHADOW; + default: UNREACHABLE(); + } + + return GL_NONE; +} + +GLenum GLVariablePrecision(const TType &type) +{ + if (type.getBasicType() == EbtFloat) + { + switch (type.getPrecision()) + { + case EbpHigh: + return GL_HIGH_FLOAT; + case EbpMedium: + return GL_MEDIUM_FLOAT; + case EbpLow: + return GL_LOW_FLOAT; + case EbpUndefined: + // Should be defined as the default precision by the parser + default: + UNREACHABLE(); + } + } + else if (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt) + { + switch (type.getPrecision()) + { + case EbpHigh: + return GL_HIGH_INT; + case EbpMedium: + return GL_MEDIUM_INT; + case EbpLow: + return GL_LOW_INT; + case EbpUndefined: + // Should be defined as the default precision by the parser + default: + UNREACHABLE(); + } + } + + // Other types (boolean, sampler) don't have a precision + return GL_NONE; +} + +TString ArrayString(const TType &type) +{ + if (!type.isArray()) + { + return ""; + } + + return "[" + str(type.getArraySize()) + "]"; +} + +bool IsVaryingOut(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqVaryingOut: + case EvqInvariantVaryingOut: + case EvqSmoothOut: + case EvqFlatOut: + case EvqCentroidOut: + case EvqVertexOut: + return true; + + default: break; + } + + return false; +} + +bool IsVaryingIn(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqVaryingIn: + case EvqInvariantVaryingIn: + case EvqSmoothIn: + case EvqFlatIn: + case EvqCentroidIn: + case EvqFragmentIn: + return true; + + default: break; + } + + return false; +} + +bool IsVarying(TQualifier qualifier) +{ + return IsVaryingIn(qualifier) || IsVaryingOut(qualifier); +} + +InterpolationType GetInterpolationType(TQualifier qualifier) +{ + switch (qualifier) + { + case EvqFlatIn: + case EvqFlatOut: + return INTERPOLATION_FLAT; + + case EvqSmoothIn: + case EvqSmoothOut: + case EvqVertexOut: + case EvqFragmentIn: + case EvqVaryingIn: + case EvqVaryingOut: + return INTERPOLATION_SMOOTH; + + case EvqCentroidIn: + case EvqCentroidOut: + return INTERPOLATION_CENTROID; + + default: UNREACHABLE(); + return INTERPOLATION_SMOOTH; + } +} + +template +void GetVariableTraverser::traverse(const TType &type, const TString &name) +{ + const TStructure *structure = type.getStruct(); + + VarT variable; + variable.name = name.c_str(); + variable.arraySize = static_cast(type.getArraySize()); + + if (!structure) + { + variable.type = GLVariableType(type); + variable.precision = GLVariablePrecision(type); + } + else + { + variable.type = GL_STRUCT_ANGLEX; + + mOutputStack.push(&variable.fields); + + const TFieldList &fields = structure->fields(); + + for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++) + { + TField *field = fields[fieldIndex]; + traverse(*field->type(), field->name()); + } + + mOutputStack.pop(); + } + + visitVariable(&variable); + + ASSERT(!mOutputStack.empty()); + mOutputStack.top()->push_back(variable); +} + +template +GetVariableTraverser::GetVariableTraverser(std::vector *output) +{ + ASSERT(output); + mOutputStack.push(output); +} + +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; + } +} + +} diff --git a/src/3rdparty/angle/src/compiler/translator/util.h b/src/3rdparty/angle/src/compiler/translator/util.h index dc69f39060..5c214dd4fb 100644 --- a/src/3rdparty/angle/src/compiler/translator/util.h +++ b/src/3rdparty/angle/src/compiler/translator/util.h @@ -7,6 +7,12 @@ #ifndef COMPILER_UTIL_H #define COMPILER_UTIL_H +#include + +#include "compiler/translator/Types.h" +#include "angle_gl.h" +#include "common/shadervars.h" + // atof_clamp is like atof but // 1. it forces C locale, i.e. forcing '.' as decimal point. // 2. it clamps the value to -FLT_MAX or FLT_MAX if overflow happens. @@ -17,4 +23,44 @@ extern bool atof_clamp(const char *str, float *value); // Return false if overflow happens. extern bool atoi_clamp(const char *str, int *value); +namespace sh +{ + +GLenum GLVariableType(const TType &type); +GLenum GLVariablePrecision(const TType &type); +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); + + protected: + // May be overloaded + virtual void visitVariable(VarT *newVar) {} + + private: + std::stack *> mOutputStack; +}; + +struct GetInterfaceBlockFieldTraverser : public GetVariableTraverser +{ + public: + GetInterfaceBlockFieldTraverser(std::vector *output, bool isRowMajorMatrix); + + private: + virtual void visitVariable(InterfaceBlockField *newField); + + bool mIsRowMajorMatrix; +}; + +} + #endif // COMPILER_UTIL_H diff --git a/src/3rdparty/angle/src/libEGL/Config.cpp b/src/3rdparty/angle/src/libEGL/Config.cpp index 5488cb6f4f..fdc41a95f0 100644 --- a/src/3rdparty/angle/src/libEGL/Config.cpp +++ b/src/3rdparty/angle/src/libEGL/Config.cpp @@ -13,8 +13,8 @@ #include #include -#include -#include +#include "angle_gl.h" +#include #include "common/debug.h" @@ -36,6 +36,13 @@ Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLi mBlueSize = 5; mAlphaSize = 1; break; + case GL_BGR5_A1_ANGLEX: + mBufferSize = 16; + mRedSize = 5; + mGreenSize = 5; + mBlueSize = 5; + mAlphaSize = 1; + break; case GL_RGBA8_OES: mBufferSize = 32; mRedSize = 8; @@ -122,6 +129,12 @@ Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLi mTransparentRedValue = 0; mTransparentGreenValue = 0; mTransparentBlueValue = 0; + + if (desc.es3Capable) + { + mRenderableType |= EGL_OPENGL_ES3_BIT_KHR; + mConformant |= EGL_OPENGL_ES3_BIT_KHR; + } } EGLConfig Config::getHandle() const diff --git a/src/3rdparty/angle/src/libEGL/Config.h b/src/3rdparty/angle/src/libEGL/Config.h index 680337b700..98441142f4 100644 --- a/src/3rdparty/angle/src/libEGL/Config.h +++ b/src/3rdparty/angle/src/libEGL/Config.h @@ -11,7 +11,6 @@ #ifndef INCLUDE_CONFIG_H_ #define INCLUDE_CONFIG_H_ -#define EGLAPI #include #include diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp index e75a4b6440..7cd83c3db4 100644 --- a/src/3rdparty/angle/src/libEGL/Display.cpp +++ b/src/3rdparty/angle/src/libEGL/Display.cpp @@ -1,6 +1,5 @@ -#include "../libGLESv2/precompiled.h" // -// Copyright (c) 2002-2013 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. // @@ -14,9 +13,11 @@ #include #include #include +#include +#include #include "common/debug.h" -#include "libGLESv2/mathutil.h" +#include "common/mathutil.h" #include "libGLESv2/main.h" #include "libGLESv2/Context.h" #include "libGLESv2/renderer/SwapChain.h" @@ -26,43 +27,57 @@ namespace egl { -namespace + +typedef std::map DisplayMap; +static DisplayMap *GetDisplayMap() { - typedef std::map DisplayMap; - DisplayMap displays; + static DisplayMap displays; + return &displays; } -egl::Display *Display::getDisplay(EGLNativeDisplayType displayId) +egl::Display *Display::getDisplay(EGLNativeDisplayType displayId, EGLint displayType) { - if (displays.find(displayId) != displays.end()) + DisplayMap *displays = GetDisplayMap(); + DisplayMap::const_iterator iter = displays->find(displayId); + if (iter != displays->end()) { - return displays[displayId]; + return iter->second; } - + // FIXME: Check if displayId is a valid display device context - egl::Display *display = new egl::Display(displayId); + egl::Display *display = new egl::Display(displayId, displayType); + displays->insert(std::make_pair(displayId, display)); - displays[displayId] = display; return display; } -Display::Display(EGLNativeDisplayType displayId) +Display::Display(EGLNativeDisplayType displayId, EGLint displayType) + : mDisplayId(displayId), + mRequestedDisplayType(displayType), + mRenderer(NULL) { - mDisplayId = displayId; - mRenderer = NULL; +#if defined(ANGLE_PLATFORM_WINRT) + if (mDisplayId) + mDisplayId->AddRef(); +#endif } Display::~Display() { terminate(); - DisplayMap::iterator thisDisplay = displays.find(mDisplayId); - - if (thisDisplay != displays.end()) + DisplayMap *displays = GetDisplayMap(); + DisplayMap::iterator iter = displays->find(mDisplayId); + if (iter != displays->end()) { - displays.erase(thisDisplay); + displays->erase(iter); } + +#if defined(ANGLE_PLATFORM_WINRT) + if (mDisplayId) + mDisplayId->Release(); +#endif } bool Display::initialize() @@ -72,8 +87,8 @@ bool Display::initialize() return true; } - mRenderer = glCreateRenderer(this, mDisplayId); - + mRenderer = glCreateRenderer(this, mDisplayId, mRequestedDisplayType); + if (!mRenderer) { terminate(); @@ -82,16 +97,16 @@ bool Display::initialize() EGLint minSwapInterval = mRenderer->getMinSwapInterval(); EGLint maxSwapInterval = mRenderer->getMaxSwapInterval(); - EGLint maxTextureWidth = mRenderer->getMaxTextureWidth(); - EGLint maxTextureHeight = mRenderer->getMaxTextureHeight(); + EGLint maxTextureSize = mRenderer->getRendererCaps().max2DTextureSize; rx::ConfigDesc *descList; int numConfigs = mRenderer->generateConfigs(&descList); ConfigSet configSet; for (int i = 0; i < numConfigs; ++i) - configSet.add(descList[i], minSwapInterval, maxSwapInterval, - maxTextureWidth, maxTextureHeight); + { + configSet.add(descList[i], minSwapInterval, maxSwapInterval, maxTextureSize, maxTextureSize); + } // Give the sorted configs a unique ID and store them internally EGLint index = 1; @@ -113,7 +128,7 @@ bool Display::initialize() return false; } - initExtensionString(); + initDisplayExtensionString(); initVendorString(); return true; @@ -192,6 +207,10 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co const Config *configuration = mConfigSet.get(config); EGLint postSubBufferSupported = EGL_FALSE; + EGLint width = 0; + EGLint height = 0; + EGLint fixedSize = EGL_FALSE; + if (attribList) { while (*attribList != EGL_NONE) @@ -212,6 +231,15 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co case EGL_POST_SUB_BUFFER_SUPPORTED_NV: postSubBufferSupported = attribList[1]; break; + case EGL_WIDTH: + width = attribList[1]; + break; + case EGL_HEIGHT: + height = attribList[1]; + break; + case EGL_FIXED_SIZE_ANGLE: + fixedSize = attribList[1]; + break; case EGL_VG_COLORSPACE: return error(EGL_BAD_MATCH, EGL_NO_SURFACE); case EGL_VG_ALPHA_FORMAT: @@ -224,6 +252,17 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co } } + if (width < 0 || height < 0) + { + return error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); + } + + if (!fixedSize) + { + width = -1; + height = -1; + } + if (hasExistingWindowSurface(window)) { return error(EGL_BAD_ALLOC, EGL_NO_SURFACE); @@ -235,7 +274,7 @@ EGLSurface Display::createWindowSurface(EGLNativeWindowType window, EGLConfig co return EGL_NO_SURFACE; } - Surface *surface = new Surface(this, configuration, window, postSubBufferSupported); + Surface *surface = new Surface(this, configuration, window, fixedSize, width, height, postSubBufferSupported); if (!surface->initialize()) { @@ -320,7 +359,7 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, return error(EGL_BAD_ATTRIBUTE, EGL_NO_SURFACE); } - if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getNonPower2TextureSupport() && (!gl::isPow2(width) || !gl::isPow2(height))) + if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getRendererExtensions().textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height))) { return error(EGL_BAD_MATCH, EGL_NO_SURFACE); } @@ -361,22 +400,29 @@ EGLSurface Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, return success(surface); } -EGLContext Display::createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess) +EGLContext Display::createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, bool robustAccess) { if (!mRenderer) { - return NULL; + return EGL_NO_CONTEXT; } else if (mRenderer->testDeviceLost(false)) // Lost device { if (!restoreLostDevice()) - return NULL; + { + return error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT); + } } - gl::Context *context = glCreateContext(shareContext, mRenderer, notifyResets, robustAccess); + if (clientVersion > 2 && mRenderer->getMajorShaderModel() < 4) + { + return error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); + } + + gl::Context *context = glCreateContext(clientVersion, shareContext, mRenderer, notifyResets, robustAccess); mContextSet.insert(context); - return context; + return success(context); } bool Display::restoreLostDevice() @@ -470,51 +516,84 @@ bool Display::hasExistingWindowSurface(EGLNativeWindowType window) return false; } -void Display::initExtensionString() +std::string Display::generateClientExtensionString() { - bool shareHandleSupported = mRenderer->getShareHandleSupport(); + std::vector extensions; - mExtensionString = ""; + extensions.push_back("EGL_EXT_client_extensions"); - // Multi-vendor (EXT) extensions - mExtensionString += "EGL_EXT_create_context_robustness "; + extensions.push_back("ANGLE_platform_angle"); - // ANGLE-specific extensions - if (shareHandleSupported) + if (supportsPlatformD3D()) { - mExtensionString += "EGL_ANGLE_d3d_share_handle_client_buffer "; + extensions.push_back("ANGLE_platform_angle_d3d"); } - mExtensionString += "EGL_ANGLE_query_surface_pointer "; - -#if defined(ANGLE_ENABLE_D3D9) - HMODULE swiftShader = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); - if (swiftShader) + if (supportsPlatformOpenGL()) { - mExtensionString += "EGL_ANGLE_software_display "; + extensions.push_back("ANGLE_platform_angle_opengl"); } -#endif - if (shareHandleSupported) + std::ostringstream stream; + std::copy(extensions.begin(), extensions.end(), std::ostream_iterator(stream, " ")); + return stream.str(); +} + +void Display::initDisplayExtensionString() +{ + std::vector extensions; + + // Multi-vendor (EXT) extensions + extensions.push_back("EGL_EXT_create_context_robustness"); + + // ANGLE-specific extensions + if (mRenderer->getShareHandleSupport()) { - mExtensionString += "EGL_ANGLE_surface_d3d_texture_2d_share_handle "; + extensions.push_back("EGL_ANGLE_d3d_share_handle_client_buffer"); + extensions.push_back("EGL_ANGLE_surface_d3d_texture_2d_share_handle"); } + extensions.push_back("EGL_ANGLE_query_surface_pointer"); + extensions.push_back("EGL_ANGLE_window_fixed_size"); + if (mRenderer->getPostSubBufferSupport()) { - mExtensionString += "EGL_NV_post_sub_buffer"; + extensions.push_back("EGL_NV_post_sub_buffer"); } - std::string::size_type end = mExtensionString.find_last_not_of(' '); - if (end != std::string::npos) + // TODO: complete support for the EGL_KHR_create_context extension + //extensions.push_back("EGL_KHR_create_context"); + + std::ostringstream stream; + std::copy(extensions.begin(), extensions.end(), std::ostream_iterator(stream, " ")); + mDisplayExtensionString = stream.str(); +} + +const char *Display::getExtensionString(egl::Display *display) +{ + if (display != EGL_NO_DISPLAY) { - mExtensionString.resize(end+1); + return display->mDisplayExtensionString.c_str(); } + else + { + static std::string clientExtensions = generateClientExtensionString(); + return clientExtensions.c_str(); + } +} + +bool Display::supportsPlatformD3D() +{ +#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11) + return true; +#else + return false; +#endif } -const char *Display::getExtensionString() const +bool Display::supportsPlatformOpenGL() { - return mExtensionString.c_str(); + return false; } void Display::initVendorString() @@ -527,7 +606,6 @@ 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/Display.h b/src/3rdparty/angle/src/libEGL/Display.h index cd07bb3388..73ba7673ff 100644 --- a/src/3rdparty/angle/src/libEGL/Display.h +++ b/src/3rdparty/angle/src/libEGL/Display.h @@ -33,14 +33,19 @@ class Display bool initialize(); void terminate(); - static egl::Display *getDisplay(EGLNativeDisplayType displayId); + static egl::Display *getDisplay(EGLNativeDisplayType displayId, EGLint displayType); + + static const char *getExtensionString(egl::Display *display); + + static bool supportsPlatformD3D(); + static bool supportsPlatformOpenGL(); bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig); bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value); EGLSurface createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList); EGLSurface createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList); - EGLContext createContext(EGLConfig configHandle, const gl::Context *shareContext, bool notifyResets, bool robustAccess); + EGLContext createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets, bool robustAccess); void destroySurface(egl::Surface *surface); void destroyContext(gl::Context *context); @@ -60,17 +65,18 @@ class Display const char *getExtensionString() const; const char *getVendorString() const; + EGLNativeDisplayType getDisplayId() const { return mDisplayId; } + private: DISALLOW_COPY_AND_ASSIGN(Display); - Display(EGLNativeDisplayType displayId); + Display(EGLNativeDisplayType displayId, EGLint displayType); bool restoreLostDevice(); EGLNativeDisplayType mDisplayId; + EGLint mRequestedDisplayType; - bool mSoftwareDevice; - typedef std::set SurfaceSet; SurfaceSet mSurfaceSet; @@ -81,9 +87,12 @@ class Display rx::Renderer *mRenderer; - void initExtensionString(); + static std::string generateClientExtensionString(); + + void initDisplayExtensionString(); + std::string mDisplayExtensionString; + void initVendorString(); - std::string mExtensionString; std::string mVendorString; }; } diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp index a2e2306ae5..fa7996152a 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.cpp +++ b/src/3rdparty/angle/src/libEGL/Surface.cpp @@ -1,6 +1,5 @@ -#include "../libGLESv2/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. // @@ -23,90 +22,20 @@ #include "libEGL/main.h" #include "libEGL/Display.h" -#if defined(ANGLE_OS_WINRT) -#include -#include -#include -#include - -static bool getCoreWindowSize(const EGLNativeWindowType win, int *width, int *height) -{ - Microsoft::WRL::ComPtr window; - HRESULT hr = win->QueryInterface(IID_PPV_ARGS(&window)); - if (FAILED(hr)) - { - ERR("Failed to cast native display pointer to ICoreWindow *."); - return false; - } - -#if _MSC_VER<=1700 - Microsoft::WRL::ComPtr displayInformation; - hr = RoGetActivationFactory(Microsoft::WRL::Wrappers::HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), - IID_PPV_ARGS(&displayInformation)); -#else - Microsoft::WRL::ComPtr displayInformationFactory; - hr = RoGetActivationFactory(Microsoft::WRL::Wrappers::HString::MakeReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(), - IID_PPV_ARGS(&displayInformationFactory)); - if (FAILED(hr)) - { - ERR("Failed to get display information factory."); - return false; - } - - Microsoft::WRL::ComPtr displayInformation; - hr = displayInformationFactory->GetForCurrentView(&displayInformation); -#endif - if (FAILED(hr)) - { - ERR("Failed to get display information."); - return false; - } - -#if defined(ANGLE_OS_WINPHONE) && _MSC_VER>=1800 // Windows Phone 8.1 - Microsoft::WRL::ComPtr displayInformation2; - hr = displayInformation.As(&displayInformation2); - if (FAILED(hr)) - { - ERR("Failed to get extended display information."); - return false; - } - - DOUBLE scaleFactor; - hr = displayInformation2->get_RawPixelsPerViewPixel(&scaleFactor); - if (FAILED(hr)) - { - ERR("Failed to get raw pixels per view pixel."); - return false; - } -#else - ABI::Windows::Graphics::Display::ResolutionScale resolutionScale; - hr = displayInformation->get_ResolutionScale(&resolutionScale); - if (FAILED(hr)) - { - ERR("Failed to get resolution scale."); - return false; - } - DOUBLE scaleFactor = DOUBLE(resolutionScale) / 100.0; -#endif - - ABI::Windows::Foundation::Rect windowRect; - hr = window->get_Bounds(&windowRect); - if (FAILED(hr)) - { - ERR("Failed to get ICoreWindow bounds."); - return false; - } - - *width = std::floor(windowRect.Width * scaleFactor + 0.5); - *height = std::floor(windowRect.Height * scaleFactor + 0.5); - return true; -} +#if defined(ANGLE_PLATFORM_WINRT) +# include "wrl.h" +# include "windows.graphics.display.h" +# include "windows.ui.core.h" +using namespace ABI::Windows::Graphics::Display; +using namespace ABI::Windows::Foundation; +using namespace ABI::Windows::UI::Core; +using namespace Microsoft::WRL; #endif namespace egl { -Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint postSubBufferSupported) +Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported) : mDisplay(display), mConfig(config), mWindow(window), mPostSubBufferSupported(postSubBufferSupported) { mRenderer = mDisplay->getRenderer(); @@ -120,9 +49,21 @@ Surface::Surface(Display *display, const Config *config, EGLNativeWindowType win mRenderBuffer = EGL_BACK_BUFFER; mSwapBehavior = EGL_BUFFER_PRESERVED; mSwapInterval = -1; - mWidth = -1; - mHeight = -1; + mWidth = width; + mHeight = height; setSwapInterval(1); + mFixedSize = fixedSize; + mSwapFlags = rx::SWAP_NORMAL; +#if defined(ANGLE_PLATFORM_WINRT) + if (mWindow) + mWindow->AddRef(); + mScaleFactor = 1.0; + mSizeToken.value = 0; + mDpiToken.value = 0; +# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP + mOrientationToken.value = 0; +# endif +#endif subclassWindow(); } @@ -142,16 +83,88 @@ Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGL mSwapBehavior = EGL_BUFFER_PRESERVED; mSwapInterval = -1; setSwapInterval(1); + // This constructor is for offscreen surfaces, which are always fixed-size. + mFixedSize = EGL_TRUE; + mSwapFlags = rx::SWAP_NORMAL; +#if defined(ANGLE_PLATFORM_WINRT) + mScaleFactor = 1.0; + mSizeToken.value = 0; + mDpiToken.value = 0; +# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP + mOrientationToken.value = 0; +# endif +#endif } Surface::~Surface() { +#if defined(ANGLE_PLATFORM_WINRT) + if (mSizeToken.value) { + ComPtr coreWindow; + HRESULT hr = mWindow->QueryInterface(coreWindow.GetAddressOf()); + ASSERT(SUCCEEDED(hr)); + + hr = coreWindow->remove_SizeChanged(mSizeToken); + ASSERT(SUCCEEDED(hr)); + } + if (mDpiToken.value) { + ComPtr displayInformation; + HRESULT hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf()); + ASSERT(SUCCEEDED(hr)); + + hr = displayInformation->remove_DpiChanged(mDpiToken); + ASSERT(SUCCEEDED(hr)); + } +# if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP + if (mOrientationToken.value) { + ComPtr displayInformation; + HRESULT hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf()); + ASSERT(SUCCEEDED(hr)); + + hr = displayInformation->remove_OrientationChanged(mOrientationToken); + ASSERT(SUCCEEDED(hr)); + } +# endif +#endif unsubclassWindow(); release(); } bool Surface::initialize() { +#if defined(ANGLE_PLATFORM_WINRT) + if (!mFixedSize) { + HRESULT hr; + ComPtr displayInformation; + hr = mDisplay->getDisplayId()->QueryInterface(displayInformation.GetAddressOf()); + ASSERT(SUCCEEDED(hr)); + onDpiChanged(displayInformation.Get(), 0); + hr = displayInformation->add_DpiChanged(Callback>(this, &Surface::onDpiChanged).Get(), + &mDpiToken); + ASSERT(SUCCEEDED(hr)); + +# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP + onOrientationChanged(displayInformation.Get(), 0); + hr = displayInformation->add_OrientationChanged(Callback>(this, &Surface::onOrientationChanged).Get(), + &mOrientationToken); + ASSERT(SUCCEEDED(hr)); +# endif + + ComPtr coreWindow; + hr = mWindow->QueryInterface(coreWindow.GetAddressOf()); + ASSERT(SUCCEEDED(hr)); + + Rect rect; + hr = coreWindow->get_Bounds(&rect); + ASSERT(SUCCEEDED(hr)); + mWidth = rect.Width * mScaleFactor; + mHeight = rect.Height * mScaleFactor; + hr = coreWindow->add_SizeChanged(Callback>(this, &Surface::onSizeChanged).Get(), + &mSizeToken); + ASSERT(SUCCEEDED(hr)); + } +#endif + if (!resetSwapChain()) return false; @@ -168,6 +181,11 @@ void Surface::release() mTexture->releaseTexImage(); mTexture = NULL; } + +#if defined(ANGLE_PLATFORM_WINRT) + if (mWindow) + mWindow->Release(); +#endif } bool Surface::resetSwapChain() @@ -177,9 +195,9 @@ bool Surface::resetSwapChain() int width; int height; - if (mWindow) +#if !defined(ANGLE_PLATFORM_WINRT) + if (!mFixedSize) { -#if !defined(ANGLE_OS_WINRT) RECT windowRect; if (!GetClientRect(getWindowHandle(), &windowRect)) { @@ -191,14 +209,9 @@ bool Surface::resetSwapChain() width = windowRect.right - windowRect.left; height = windowRect.bottom - windowRect.top; -#else - if (!getCoreWindowSize(mWindow, &width, &height)) - { - return false; - } -#endif } else +#endif { // non-window surface - size is determined at creation width = mWidth; @@ -228,7 +241,7 @@ bool Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight) ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); ASSERT(mSwapChain); - EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight); + EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight)); if (status == EGL_CONTEXT_LOST) { @@ -251,7 +264,7 @@ bool Surface::resetSwapChain(int backbufferWidth, int backbufferHeight) ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0); ASSERT(mSwapChain); - EGLint status = mSwapChain->reset(backbufferWidth, backbufferHeight, mSwapInterval); + EGLint status = mSwapChain->reset(std::max(1, backbufferWidth), std::max(1, backbufferHeight), mSwapInterval); if (status == EGL_CONTEXT_LOST) { @@ -292,7 +305,7 @@ bool Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) return true; } - EGLint status = mSwapChain->swapRect(x, y, width, height); + EGLint status = mSwapChain->swapRect(x, y, width, height, mSwapFlags); if (status == EGL_CONTEXT_LOST) { @@ -318,7 +331,7 @@ EGLNativeWindowType Surface::getWindowHandle() #define kSurfaceProperty _TEXT("Egl::SurfaceOwner") #define kParentWndProc _TEXT("Egl::SurfaceParentWndProc") -#if !defined(ANGLE_OS_WINRT) +#if !defined(ANGLE_PLATFORM_WINRT) static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { if (message == WM_SIZE) @@ -336,9 +349,7 @@ static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam void Surface::subclassWindow() { -#if defined(ANGLE_OS_WINRT) - mWindowSubclassed = false; -#else +#if !defined(ANGLE_PLATFORM_WINRT) if (!mWindow) { return; @@ -362,12 +373,14 @@ void Surface::subclassWindow() SetProp(mWindow, kSurfaceProperty, reinterpret_cast(this)); SetProp(mWindow, kParentWndProc, reinterpret_cast(oldWndProc)); mWindowSubclassed = true; +#else + mWindowSubclassed = false; #endif } void Surface::unsubclassWindow() { -#if !defined(ANGLE_OS_WINRT) +#if !defined(ANGLE_PLATFORM_WINRT) if(!mWindowSubclassed) { return; @@ -384,6 +397,7 @@ void Surface::unsubclassWindow() if(parentWndFunc) { LONG_PTR prevWndFunc = SetWindowLongPtr(mWindow, GWLP_WNDPROC, parentWndFunc); + UNUSED_ASSERTION_VARIABLE(prevWndFunc); ASSERT(prevWndFunc == reinterpret_cast(SurfaceWindowProc)); } @@ -395,33 +409,25 @@ void Surface::unsubclassWindow() bool Surface::checkForOutOfDateSwapChain() { -#if !defined(ANGLE_OS_WINRT) - RECT client; - if (!GetClientRect(getWindowHandle(), &client)) - { - ASSERT(false); - return false; - } - - // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information. - int clientWidth = client.right - client.left; - int clientHeight = client.bottom - client.top; -#else - int clientWidth; - int clientHeight; - if (!getCoreWindowSize(mWindow, &clientWidth, &clientHeight)) - { - return false; - } -#endif - bool sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); - -#if !defined(ANGLE_OS_WINRT) - if (IsIconic(getWindowHandle())) + int clientWidth = getWidth(); + int clientHeight = getHeight(); + bool sizeDirty = false; +#if !defined(ANGLE_PLATFORM_WINRT) + if (!mFixedSize && !IsIconic(getWindowHandle())) { + RECT client; // The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized // because that's not a useful size to render to. - sizeDirty = false; + if (!GetClientRect(getWindowHandle(), &client)) + { + ASSERT(false); + return false; + } + + // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information. + clientWidth = client.right - client.left; + clientHeight = client.bottom - client.top; + sizeDirty = clientWidth != getWidth() || clientHeight != getHeight(); } #endif @@ -461,18 +467,8 @@ bool Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) // Spec is not clear about how this should be handled. return true; } - - return swapRect(x, y, width, height); -} - -EGLint Surface::getWidth() const -{ - return mWidth; -} -EGLint Surface::getHeight() const -{ - return mHeight; + return swapRect(x, y, width, height); } EGLint Surface::isPostSubBufferSupported() const @@ -491,7 +487,7 @@ void Surface::setSwapInterval(EGLint interval) { return; } - + mSwapInterval = interval; mSwapInterval = std::max(mSwapInterval, mRenderer->getMinSwapInterval()); mSwapInterval = std::min(mSwapInterval, mRenderer->getMaxSwapInterval()); @@ -499,6 +495,36 @@ void Surface::setSwapInterval(EGLint interval) mSwapIntervalDirty = true; } +EGLint Surface::getConfigID() const +{ + return mConfig->mConfigID; +} + +EGLint Surface::getWidth() const +{ + return mWidth; +} + +EGLint Surface::getHeight() const +{ + return mHeight; +} + +EGLint Surface::getPixelAspectRatio() const +{ + return mPixelAspectRatio; +} + +EGLenum Surface::getRenderBuffer() const +{ + return mRenderBuffer; +} + +EGLenum Surface::getSwapBehavior() const +{ + return mSwapBehavior; +} + EGLenum Surface::getTextureFormat() const { return mTextureFormat; @@ -519,8 +545,82 @@ gl::Texture2D *Surface::getBoundTexture() const return mTexture; } +EGLint Surface::isFixedSize() const +{ + return mFixedSize; +} + EGLenum Surface::getFormat() const { return mConfig->mRenderTargetFormat; } + +#if defined(ANGLE_PLATFORM_WINRT) + +HRESULT Surface::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *args) +{ + HRESULT hr; + Size size; + hr = args->get_Size(&size); + ASSERT(SUCCEEDED(hr)); + + resizeSwapChain(std::floor(size.Width * mScaleFactor + 0.5), + std::floor(size.Height * mScaleFactor + 0.5)); + + if (static_cast(getCurrentDrawSurface()) == this) + { + glMakeCurrent(glGetCurrentContext(), static_cast(getCurrentDisplay()), this); + } + + return S_OK; +} + +HRESULT Surface::onDpiChanged(IDisplayInformation *displayInformation, IInspectable *) +{ + HRESULT hr; +# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP + ComPtr displayInformation2; + hr = displayInformation->QueryInterface(displayInformation2.GetAddressOf()); + ASSERT(SUCCEEDED(hr)); + + hr = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor); + ASSERT(SUCCEEDED(hr)); +# else + ResolutionScale resolutionScale; + hr = displayInformation->get_ResolutionScale(&resolutionScale); + ASSERT(SUCCEEDED(hr)); + + mScaleFactor = double(resolutionScale) / 100.0; +# endif + return S_OK; +} + +# if WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP +HRESULT Surface::onOrientationChanged(IDisplayInformation *displayInformation, IInspectable *) +{ + HRESULT hr; + DisplayOrientations orientation; + hr = displayInformation->get_CurrentOrientation(&orientation); + ASSERT(SUCCEEDED(hr)); + switch (orientation) { + default: + case DisplayOrientations_Portrait: + mSwapFlags = rx::SWAP_NORMAL; + break; + case DisplayOrientations_Landscape: + mSwapFlags = rx::SWAP_ROTATE_90; + break; + case DisplayOrientations_LandscapeFlipped: + mSwapFlags = rx::SWAP_ROTATE_270; + break; + case DisplayOrientations_PortraitFlipped: + mSwapFlags = rx::SWAP_ROTATE_180; + break; + } + return S_OK; +} +# endif + +#endif + } diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h index 1d2303c6eb..ebffce8fed 100644 --- a/src/3rdparty/angle/src/libEGL/Surface.h +++ b/src/3rdparty/angle/src/libEGL/Surface.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,11 +11,24 @@ #ifndef LIBEGL_SURFACE_H_ #define LIBEGL_SURFACE_H_ -#define EGLAPI #include #include "common/angleutils.h" +#if defined(ANGLE_PLATFORM_WINRT) +#include +namespace ABI { namespace Windows { + namespace UI { namespace Core { + struct ICoreWindow; + struct IWindowSizeChangedEventArgs; + } } + namespace Graphics { namespace Display { + struct IDisplayInformation; + } } +} } +struct IInspectable; +#endif + namespace gl { class Texture2D; @@ -34,10 +47,10 @@ class Config; class Surface { public: - Surface(Display *display, const egl::Config *config, EGLNativeWindowType window, EGLint postSubBufferSupported); + Surface(Display *display, const egl::Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported); Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget); - ~Surface(); + virtual ~Surface(); bool initialize(); void release(); @@ -47,9 +60,6 @@ class Surface bool swap(); bool postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height); - virtual EGLint getWidth() const; - virtual EGLint getHeight() const; - virtual EGLint isPostSubBufferSupported() const; virtual rx::SwapChain *getSwapChain() const; @@ -57,6 +67,12 @@ class Surface void setSwapInterval(EGLint interval); bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update + virtual EGLint getConfigID() const; + virtual EGLint getWidth() const; + virtual EGLint getHeight() const; + virtual EGLint getPixelAspectRatio() const; + virtual EGLenum getRenderBuffer() const; + virtual EGLenum getSwapBehavior() const; virtual EGLenum getTextureFormat() const; virtual EGLenum getTextureTarget() const; virtual EGLenum getFormat() const; @@ -64,9 +80,19 @@ class Surface virtual void setBoundTexture(gl::Texture2D *texture); virtual gl::Texture2D *getBoundTexture() const; + EGLint isFixedSize() const; + private: DISALLOW_COPY_AND_ASSIGN(Surface); +#if defined(ANGLE_PLATFORM_WINRT) + HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *); + HRESULT onDpiChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *); +# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP + HRESULT onOrientationChanged(ABI::Windows::Graphics::Display::IDisplayInformation *, IInspectable *); +# endif +#endif + Display *const mDisplay; rx::Renderer *mRenderer; @@ -79,7 +105,7 @@ private: bool resetSwapChain(int backbufferWidth, int backbufferHeight); bool swapRect(EGLint x, EGLint y, EGLint width, EGLint height); - const EGLNativeWindowType mWindow; // Window that the surface is created for. + const EGLNativeWindowType mWindow; // Window that the surface is created for. bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking const egl::Config *mConfig; // EGL config surface was created with EGLint mHeight; // Height of surface @@ -99,9 +125,19 @@ private: // EGLenum vgColorSpace; // Color space for OpenVG EGLint mSwapInterval; EGLint mPostSubBufferSupported; - + EGLint mFixedSize; + EGLint mSwapFlags; + bool mSwapIntervalDirty; gl::Texture2D *mTexture; +#if defined(ANGLE_PLATFORM_WINRT) + double mScaleFactor; + EventRegistrationToken mSizeToken; + EventRegistrationToken mDpiToken; +# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP + EventRegistrationToken mOrientationToken; +# endif +#endif }; } diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp index b2944d5c0d..a08e1edeab 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.cpp +++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 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,6 +10,7 @@ #include "common/debug.h" #include "common/version.h" +#include "common/platform.h" #include "libGLESv2/Context.h" #include "libGLESv2/Texture.h" #include "libGLESv2/main.h" @@ -99,99 +100,139 @@ EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id) { EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id); - try + return egl::Display::getDisplay(display_id, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE); +} + +EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list) +{ + EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)", + platform, native_display, attrib_list); + + switch (platform) { - return egl::Display::getDisplay(display_id); + case EGL_PLATFORM_ANGLE_ANGLE: + break; + + default: + return egl::error(EGL_BAD_CONFIG, EGL_NO_DISPLAY); } - catch(std::bad_alloc&) + + EGLNativeDisplayType displayId = static_cast(native_display); +#if !defined(ANGLE_PLATFORM_WINRT) + // Validate the display device context + if (WindowFromDC(displayId) == NULL) { - return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY); + return egl::success(EGL_NO_DISPLAY); } -} - -EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) -{ - EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)", - dpy, major, minor); +#endif - try + EGLint requestedDisplayType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE; + if (attrib_list) { - if (dpy == EGL_NO_DISPLAY) + for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2) { - return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); + switch (curAttrib[0]) + { + case EGL_PLATFORM_ANGLE_TYPE_ANGLE: + requestedDisplayType = curAttrib[1]; + break; + + default: + break; + } } + } - egl::Display *display = static_cast(dpy); + switch (requestedDisplayType) + { + case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE: + break; - if (!display->initialize()) + case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE: + case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE: + case EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE: + if (!egl::Display::supportsPlatformD3D()) { - return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE); + return egl::success(EGL_NO_DISPLAY); } + break; - if (major) *major = 1; - if (minor) *minor = 4; + case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE: + case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE: + if (!egl::Display::supportsPlatformOpenGL()) + { + return egl::success(EGL_NO_DISPLAY); + } + break; - return egl::success(EGL_TRUE); + default: + return egl::success(EGL_NO_DISPLAY); } - catch(std::bad_alloc&) + + return egl::Display::getDisplay(displayId, requestedDisplayType); +} + +EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) +{ + EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)", + dpy, major, minor); + + if (dpy == EGL_NO_DISPLAY) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); } + + egl::Display *display = static_cast(dpy); + + if (!display->initialize()) + { + return egl::error(EGL_NOT_INITIALIZED, EGL_FALSE); + } + + if (major) *major = 1; + if (minor) *minor = 4; + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglTerminate(EGLDisplay dpy) { EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy); - try + if (dpy == EGL_NO_DISPLAY) { - if (dpy == EGL_NO_DISPLAY) - { - return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); - } + return egl::error(EGL_BAD_DISPLAY, EGL_FALSE); + } - egl::Display *display = static_cast(dpy); + egl::Display *display = static_cast(dpy); - display->terminate(); + display->terminate(); - return egl::success(EGL_TRUE); - } - catch(std::bad_alloc&) - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); - } + return egl::success(EGL_TRUE); } const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name) { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name); - try + egl::Display *display = static_cast(dpy); + if (!(display == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) && !validateDisplay(display)) { - egl::Display *display = static_cast(dpy); - - if (!validateDisplay(display)) - { - return NULL; - } - - switch (name) - { - case EGL_CLIENT_APIS: - return egl::success("OpenGL_ES"); - case EGL_EXTENSIONS: - return egl::success(display->getExtensionString()); - case EGL_VENDOR: - return egl::success(display->getVendorString()); - case EGL_VERSION: - return egl::success("1.4 (ANGLE " ANGLE_VERSION_STRING ")"); - } - - return egl::error(EGL_BAD_PARAMETER, (const char*)NULL); + return NULL; } - catch(std::bad_alloc&) + + switch (name) { - return egl::error(EGL_BAD_ALLOC, (const char*)NULL); + case EGL_CLIENT_APIS: + return egl::success("OpenGL_ES"); + case EGL_EXTENSIONS: + return egl::success(egl::Display::getExtensionString(display)); + case EGL_VENDOR: + return egl::success(display->getVendorString()); + case EGL_VERSION: + return egl::success("1.4 (ANGLE " ANGLE_VERSION_STRING ")"); + default: + return egl::error(EGL_BAD_PARAMETER, (const char*)NULL); } } @@ -201,33 +242,26 @@ EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint co "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", dpy, configs, config_size, num_config); - try - { - egl::Display *display = static_cast(dpy); - - if (!validateDisplay(display)) - { - return EGL_FALSE; - } + egl::Display *display = static_cast(dpy); - if (!num_config) - { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); - } + if (!validateDisplay(display)) + { + return EGL_FALSE; + } - const EGLint attribList[] = {EGL_NONE}; + if (!num_config) + { + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + } - if (!display->getConfigs(configs, attribList, config_size, num_config)) - { - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); - } + const EGLint attribList[] = {EGL_NONE}; - return egl::success(EGL_TRUE); - } - catch(std::bad_alloc&) + if (!display->getConfigs(configs, attribList, config_size, num_config)) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); } + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) @@ -236,35 +270,28 @@ EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)", dpy, attrib_list, configs, config_size, num_config); - try - { - egl::Display *display = static_cast(dpy); - - if (!validateDisplay(display)) - { - return EGL_FALSE; - } + egl::Display *display = static_cast(dpy); - if (!num_config) - { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); - } - - const EGLint attribList[] = {EGL_NONE}; + if (!validateDisplay(display)) + { + return EGL_FALSE; + } - if (!attrib_list) - { - attrib_list = attribList; - } + if (!num_config) + { + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + } - display->getConfigs(configs, attrib_list, config_size, num_config); + const EGLint attribList[] = {EGL_NONE}; - return egl::success(EGL_TRUE); - } - catch(std::bad_alloc&) + if (!attrib_list) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + attrib_list = attribList; } + + display->getConfigs(configs, attrib_list, config_size, num_config); + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) @@ -272,26 +299,19 @@ EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", dpy, config, attribute, value); - try - { - egl::Display *display = static_cast(dpy); - - if (!validateConfig(display, config)) - { - return EGL_FALSE; - } - - if (!display->getConfigAttrib(config, attribute, value)) - { - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); - } + egl::Display *display = static_cast(dpy); - return egl::success(EGL_TRUE); + if (!validateConfig(display, config)) + { + return EGL_FALSE; } - catch(std::bad_alloc&) + + if (!display->getConfigAttrib(config, attribute, value)) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); } + + return egl::success(EGL_TRUE); } EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list) @@ -299,30 +319,23 @@ EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EG EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, " "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list); - try - { - egl::Display *display = static_cast(dpy); + egl::Display *display = static_cast(dpy); - if (!validateConfig(display, config)) - { - return EGL_NO_SURFACE; - } - -#if !defined(ANGLE_OS_WINRT) - HWND window = (HWND)win; + if (!validateConfig(display, config)) + { + return EGL_NO_SURFACE; + } - if (!IsWindow(window)) - { - return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); - } -#endif +#if !defined(ANGLE_PLATFORM_WINRT) + HWND window = (HWND)win; - return display->createWindowSurface(win, config, attrib_list); - } - catch(std::bad_alloc&) + if (!IsWindow(window)) { - return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return egl::error(EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE); } +#endif + + return display->createWindowSurface(win, config, attrib_list); } EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) @@ -330,21 +343,14 @@ EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, c EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", dpy, config, attrib_list); - try - { - egl::Display *display = static_cast(dpy); - - if (!validateConfig(display, config)) - { - return EGL_NO_SURFACE; - } + egl::Display *display = static_cast(dpy); - return display->createOffscreenSurface(config, NULL, attrib_list); - } - catch(std::bad_alloc&) + if (!validateConfig(display, config)) { - return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return EGL_NO_SURFACE; } + + return display->createOffscreenSurface(config, NULL, attrib_list); } EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) @@ -352,52 +358,38 @@ EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EG EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, " "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list); - try - { - egl::Display *display = static_cast(dpy); + egl::Display *display = static_cast(dpy); - if (!validateConfig(display, config)) - { - return EGL_NO_SURFACE; - } - - UNIMPLEMENTED(); // FIXME - - return egl::success(EGL_NO_SURFACE); - } - catch(std::bad_alloc&) + if (!validateConfig(display, config)) { - return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return EGL_NO_SURFACE; } + + UNIMPLEMENTED(); // FIXME + + return egl::success(EGL_NO_SURFACE); } EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface) { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); - try - { - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = static_cast(surface); - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE) - { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); - } - - display->destroySurface((egl::Surface*)surface); - - return egl::success(EGL_TRUE); + if (!validateSurface(display, eglSurface)) + { + return EGL_FALSE; } - catch(std::bad_alloc&) + + if (surface == EGL_NO_SURFACE) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } + + display->destroySurface((egl::Surface*)surface); + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) @@ -405,84 +397,80 @@ EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", dpy, surface, attribute, value); - try - { - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = (egl::Surface*)surface; + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = (egl::Surface*)surface; - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (surface == EGL_NO_SURFACE) - { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); - } - - switch (attribute) - { - case EGL_VG_ALPHA_FORMAT: - UNIMPLEMENTED(); // FIXME - break; - case EGL_VG_COLORSPACE: - UNIMPLEMENTED(); // FIXME - break; - case EGL_CONFIG_ID: - UNIMPLEMENTED(); // FIXME - break; - case EGL_HEIGHT: - *value = eglSurface->getHeight(); - break; - case EGL_HORIZONTAL_RESOLUTION: - UNIMPLEMENTED(); // FIXME - break; - case EGL_LARGEST_PBUFFER: - UNIMPLEMENTED(); // FIXME - break; - case EGL_MIPMAP_TEXTURE: - UNIMPLEMENTED(); // FIXME - break; - case EGL_MIPMAP_LEVEL: - UNIMPLEMENTED(); // FIXME - break; - case EGL_MULTISAMPLE_RESOLVE: - UNIMPLEMENTED(); // FIXME - break; - case EGL_PIXEL_ASPECT_RATIO: - UNIMPLEMENTED(); // FIXME - break; - case EGL_RENDER_BUFFER: - UNIMPLEMENTED(); // FIXME - break; - case EGL_SWAP_BEHAVIOR: - UNIMPLEMENTED(); // FIXME - break; - case EGL_TEXTURE_FORMAT: - UNIMPLEMENTED(); // FIXME - break; - case EGL_TEXTURE_TARGET: - UNIMPLEMENTED(); // FIXME - break; - case EGL_VERTICAL_RESOLUTION: - UNIMPLEMENTED(); // FIXME - break; - case EGL_WIDTH: - *value = eglSurface->getWidth(); - break; - case EGL_POST_SUB_BUFFER_SUPPORTED_NV: - *value = eglSurface->isPostSubBufferSupported(); - break; - default: - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); - } - - return egl::success(EGL_TRUE); + if (!validateSurface(display, eglSurface)) + { + return EGL_FALSE; } - catch(std::bad_alloc&) + + if (surface == EGL_NO_SURFACE) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } + + switch (attribute) + { + case EGL_VG_ALPHA_FORMAT: + UNIMPLEMENTED(); // FIXME + break; + case EGL_VG_COLORSPACE: + UNIMPLEMENTED(); // FIXME + break; + case EGL_CONFIG_ID: + *value = eglSurface->getConfigID(); + break; + case EGL_HEIGHT: + *value = eglSurface->getHeight(); + break; + case EGL_HORIZONTAL_RESOLUTION: + UNIMPLEMENTED(); // FIXME + break; + case EGL_LARGEST_PBUFFER: + UNIMPLEMENTED(); // FIXME + break; + case EGL_MIPMAP_TEXTURE: + UNIMPLEMENTED(); // FIXME + break; + case EGL_MIPMAP_LEVEL: + UNIMPLEMENTED(); // FIXME + break; + case EGL_MULTISAMPLE_RESOLVE: + UNIMPLEMENTED(); // FIXME + break; + case EGL_PIXEL_ASPECT_RATIO: + *value = eglSurface->getPixelAspectRatio(); + break; + case EGL_RENDER_BUFFER: + *value = eglSurface->getRenderBuffer(); + break; + case EGL_SWAP_BEHAVIOR: + *value = eglSurface->getSwapBehavior(); + break; + case EGL_TEXTURE_FORMAT: + *value = eglSurface->getTextureFormat(); + break; + case EGL_TEXTURE_TARGET: + *value = eglSurface->getTextureTarget(); + break; + case EGL_VERTICAL_RESOLUTION: + UNIMPLEMENTED(); // FIXME + break; + case EGL_WIDTH: + *value = eglSurface->getWidth(); + break; + case EGL_POST_SUB_BUFFER_SUPPORTED_NV: + *value = eglSurface->isPostSubBufferSupported(); + break; + case EGL_FIXED_SIZE_ANGLE: + *value = eglSurface->isFixedSize(); + break; + default: + return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + } + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value) @@ -490,114 +478,79 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)", dpy, surface, attribute, value); - try - { - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = (egl::Surface*)surface; + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = (egl::Surface*)surface; - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } + if (!validateSurface(display, eglSurface)) + { + return EGL_FALSE; + } - if (surface == EGL_NO_SURFACE) - { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); - } + if (surface == EGL_NO_SURFACE) + { + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + } - switch (attribute) + switch (attribute) + { + case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: { - case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: - { - rx::SwapChain *swapchain = eglSurface->getSwapChain(); - *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL); - } - break; - default: - return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); + rx::SwapChain *swapchain = eglSurface->getSwapChain(); + *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL); } - - return egl::success(EGL_TRUE); - } - catch(std::bad_alloc&) - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + break; + default: + return egl::error(EGL_BAD_ATTRIBUTE, EGL_FALSE); } + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglBindAPI(EGLenum api) { EVENT("(EGLenum api = 0x%X)", api); - try + switch (api) { - switch (api) - { - case EGL_OPENGL_API: - case EGL_OPENVG_API: - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation - case EGL_OPENGL_ES_API: - break; - default: - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); - } + case EGL_OPENGL_API: + case EGL_OPENVG_API: + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); // Not supported by this implementation + case EGL_OPENGL_ES_API: + break; + default: + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + } - egl::setCurrentAPI(api); + egl::setCurrentAPI(api); - return egl::success(EGL_TRUE); - } - catch(std::bad_alloc&) - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); - } + return egl::success(EGL_TRUE); } EGLenum __stdcall eglQueryAPI(void) { EVENT("()"); - try - { - EGLenum API = egl::getCurrentAPI(); + EGLenum API = egl::getCurrentAPI(); - return egl::success(API); - } - catch(std::bad_alloc&) - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); - } + return egl::success(API); } EGLBoolean __stdcall eglWaitClient(void) { EVENT("()"); - try - { - UNIMPLEMENTED(); // FIXME + UNIMPLEMENTED(); // FIXME - return egl::success(0); - } - catch(std::bad_alloc&) - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); - } + return egl::success(0); } EGLBoolean __stdcall eglReleaseThread(void) { EVENT("()"); - try - { - eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); + eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE); - return egl::success(EGL_TRUE); - } - catch(std::bad_alloc&) - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); - } + return egl::success(EGL_TRUE); } EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) @@ -606,26 +559,19 @@ EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum bu "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)", dpy, buftype, buffer, config, attrib_list); - try - { - egl::Display *display = static_cast(dpy); - - if (!validateConfig(display, config)) - { - return EGL_NO_SURFACE; - } + egl::Display *display = static_cast(dpy); - if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer) - { - return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); - } - - return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list); + if (!validateConfig(display, config)) + { + return EGL_NO_SURFACE; } - catch(std::bad_alloc&) + + if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer) { - return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); } + + return display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list); } EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) @@ -633,145 +579,117 @@ EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)", dpy, surface, attribute, value); - try - { - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - UNIMPLEMENTED(); // FIXME + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = static_cast(surface); - return egl::success(EGL_TRUE); - } - catch(std::bad_alloc&) + if (!validateSurface(display, eglSurface)) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return EGL_FALSE; } + + UNIMPLEMENTED(); // FIXME + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); - try - { - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = static_cast(surface); - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (buffer != EGL_BACK_BUFFER) - { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); - } - - if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) - { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); - } + if (!validateSurface(display, eglSurface)) + { + return EGL_FALSE; + } - if (eglSurface->getBoundTexture()) - { - return egl::error(EGL_BAD_ACCESS, EGL_FALSE); - } + if (buffer != EGL_BACK_BUFFER) + { + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + } - if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) - { - return egl::error(EGL_BAD_MATCH, EGL_FALSE); - } + if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) + { + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + } - if (!glBindTexImage(eglSurface)) - { - return egl::error(EGL_BAD_MATCH, EGL_FALSE); - } + if (eglSurface->getBoundTexture()) + { + return egl::error(EGL_BAD_ACCESS, EGL_FALSE); + } - return egl::success(EGL_TRUE); + if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) + { + return egl::error(EGL_BAD_MATCH, EGL_FALSE); } - catch(std::bad_alloc&) + + if (!glBindTexImage(eglSurface)) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_MATCH, EGL_FALSE); } + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer); - try - { - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = static_cast(surface); - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (buffer != EGL_BACK_BUFFER) - { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); - } + if (!validateSurface(display, eglSurface)) + { + return EGL_FALSE; + } - if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) - { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); - } + if (buffer != EGL_BACK_BUFFER) + { + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + } - if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) - { - return egl::error(EGL_BAD_MATCH, EGL_FALSE); - } + if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle()) + { + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); + } - gl::Texture2D *texture = eglSurface->getBoundTexture(); + if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE) + { + return egl::error(EGL_BAD_MATCH, EGL_FALSE); + } - if (texture) - { - texture->releaseTexImage(); - } + gl::Texture2D *texture = eglSurface->getBoundTexture(); - return egl::success(EGL_TRUE); - } - catch(std::bad_alloc&) + if (texture) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + texture->releaseTexImage(); } + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval) { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval); - try - { - egl::Display *display = static_cast(dpy); + egl::Display *display = static_cast(dpy); - if (!validateDisplay(display)) - { - return EGL_FALSE; - } - - egl::Surface *draw_surface = static_cast(egl::getCurrentDrawSurface()); + if (!validateDisplay(display)) + { + return EGL_FALSE; + } - if (draw_surface == NULL) - { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); - } - - draw_surface->setSwapInterval(interval); + egl::Surface *draw_surface = static_cast(egl::getCurrentDrawSurface()); - return egl::success(EGL_TRUE); - } - catch(std::bad_alloc&) + if (draw_surface == NULL) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } + + draw_surface->setSwapInterval(interval); + + return egl::success(EGL_TRUE); } EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) @@ -779,108 +697,97 @@ EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLConte EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, " "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list); - try - { - // Get the requested client version (default is 1) and check it is two. - EGLint client_version = 1; - bool reset_notification = false; - bool robust_access = false; + // Get the requested client version (default is 1) and check it is 2 or 3. + EGLint client_version = 1; + bool reset_notification = false; + bool robust_access = false; - if (attrib_list) + if (attrib_list) + { + for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2) { - for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2) + switch (attribute[0]) { - switch (attribute[0]) + case EGL_CONTEXT_CLIENT_VERSION: + client_version = attribute[1]; + break; + case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: + if (attribute[1] == EGL_TRUE) { - case EGL_CONTEXT_CLIENT_VERSION: - client_version = attribute[1]; - break; - case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: - if (attribute[1] == EGL_TRUE) - { - return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented - // robust_access = true; - } - else if (attribute[1] != EGL_FALSE) - return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); - break; - case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT: - if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT) - reset_notification = true; - else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT) - return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); - break; - default: - return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); // Unimplemented + // robust_access = true; } + else if (attribute[1] != EGL_FALSE) + return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + break; + case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT: + if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT) + reset_notification = true; + else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT) + return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); + break; + default: + return egl::error(EGL_BAD_ATTRIBUTE, EGL_NO_CONTEXT); } } + } - if (client_version != 2) - { - return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); - } + if (client_version != 2 && client_version != 3) + { + return egl::error(EGL_BAD_CONFIG, EGL_NO_CONTEXT); + } - gl::Context *sharedContextPtr = (share_context != EGL_NO_CONTEXT ? static_cast(share_context) : NULL); + egl::Display *display = static_cast(dpy); - if (sharedContextPtr != NULL && sharedContextPtr->isResetNotificationEnabled() != reset_notification) + if (share_context) + { + gl::Context* sharedGLContext = static_cast(share_context); + + if (sharedGLContext->isResetNotificationEnabled() != reset_notification) { return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); } - egl::Display *display = static_cast(dpy); - - // Can not share contexts between displays - if (sharedContextPtr != NULL && sharedContextPtr->getRenderer() != display->getRenderer()) + if (sharedGLContext->getClientVersion() != client_version) { - return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); + return egl::error(EGL_BAD_CONTEXT, EGL_NO_CONTEXT); } - if (!validateConfig(display, config)) + // Can not share contexts between displays + if (sharedGLContext->getRenderer() != display->getRenderer()) { - return EGL_NO_CONTEXT; + return egl::error(EGL_BAD_MATCH, EGL_NO_CONTEXT); } - - EGLContext context = display->createContext(config, static_cast(share_context), reset_notification, robust_access); - - if (context) - return egl::success(context); - else - return egl::error(EGL_CONTEXT_LOST, EGL_NO_CONTEXT); } - catch(std::bad_alloc&) + + if (!validateConfig(display, config)) { - return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); + return EGL_NO_CONTEXT; } + + return display->createContext(config, client_version, static_cast(share_context), reset_notification, robust_access); } EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx); - try - { - egl::Display *display = static_cast(dpy); - gl::Context *context = static_cast(ctx); - - if (!validateContext(display, context)) - { - return EGL_FALSE; - } - - if (ctx == EGL_NO_CONTEXT) - { - return egl::error(EGL_BAD_CONTEXT, EGL_FALSE); - } + egl::Display *display = static_cast(dpy); + gl::Context *context = static_cast(ctx); - display->destroyContext(context); - - return egl::success(EGL_TRUE); + if (!validateContext(display, context)) + { + return EGL_FALSE; } - catch(std::bad_alloc&) + + if (ctx == EGL_NO_CONTEXT) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_BAD_CONTEXT, EGL_FALSE); } + + display->destroyContext(context); + + return egl::success(EGL_TRUE); } EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) @@ -888,95 +795,74 @@ EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, draw, read, ctx); - try + egl::Display *display = static_cast(dpy); + gl::Context *context = static_cast(ctx); + + if (ctx != EGL_NO_CONTEXT && !validateContext(display, context)) { - egl::Display *display = static_cast(dpy); - gl::Context *context = static_cast(ctx); + return EGL_FALSE; + } - if (ctx != EGL_NO_CONTEXT && !validateContext(display, context)) + if (dpy != EGL_NO_DISPLAY) + { + rx::Renderer *renderer = display->getRenderer(); + if (renderer->testDeviceLost(true)) { return EGL_FALSE; } - if (dpy != EGL_NO_DISPLAY) + if (renderer->isDeviceLost()) { - rx::Renderer *renderer = display->getRenderer(); - if (renderer->testDeviceLost(true)) - { - return EGL_FALSE; - } - - if (renderer->isDeviceLost()) - { - return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); - } + return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); } + } - if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast(draw))) || - (read != EGL_NO_SURFACE && !validateSurface(display, static_cast(read)))) - { - return EGL_FALSE; - } + if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast(draw))) || + (read != EGL_NO_SURFACE && !validateSurface(display, static_cast(read)))) + { + return EGL_FALSE; + } - if (draw != read) - { - UNIMPLEMENTED(); // FIXME - } + if (draw != read) + { + UNIMPLEMENTED(); // FIXME + } - egl::setCurrentDisplay(dpy); - egl::setCurrentDrawSurface(draw); - egl::setCurrentReadSurface(read); + egl::setCurrentDisplay(dpy); + egl::setCurrentDrawSurface(draw); + egl::setCurrentReadSurface(read); - glMakeCurrent(context, display, static_cast(draw)); + glMakeCurrent(context, display, static_cast(draw)); - return egl::success(EGL_TRUE); - } - catch(std::bad_alloc&) - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); - } + return egl::success(EGL_TRUE); } EGLContext __stdcall eglGetCurrentContext(void) { EVENT("()"); - try - { - EGLContext context = glGetCurrentContext(); + EGLContext context = glGetCurrentContext(); - return egl::success(context); - } - catch(std::bad_alloc&) - { - return egl::error(EGL_BAD_ALLOC, EGL_NO_CONTEXT); - } + return egl::success(context); } EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw) { EVENT("(EGLint readdraw = %d)", readdraw); - try + if (readdraw == EGL_READ) { - if (readdraw == EGL_READ) - { - EGLSurface read = egl::getCurrentReadSurface(); - return egl::success(read); - } - else if (readdraw == EGL_DRAW) - { - EGLSurface draw = egl::getCurrentDrawSurface(); - return egl::success(draw); - } - else - { - return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); - } + EGLSurface read = egl::getCurrentReadSurface(); + return egl::success(read); } - catch(std::bad_alloc&) + else if (readdraw == EGL_DRAW) { - return egl::error(EGL_BAD_ALLOC, EGL_NO_SURFACE); + EGLSurface draw = egl::getCurrentDrawSurface(); + return egl::success(draw); + } + else + { + return egl::error(EGL_BAD_PARAMETER, EGL_NO_SURFACE); } } @@ -984,16 +870,9 @@ EGLDisplay __stdcall eglGetCurrentDisplay(void) { EVENT("()"); - try - { - EGLDisplay dpy = egl::getCurrentDisplay(); + EGLDisplay dpy = egl::getCurrentDisplay(); - return egl::success(dpy); - } - catch(std::bad_alloc&) - { - return egl::error(EGL_BAD_ALLOC, EGL_NO_DISPLAY); - } + return egl::success(dpy); } EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) @@ -1001,90 +880,62 @@ EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attr EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)", dpy, ctx, attribute, value); - try - { - egl::Display *display = static_cast(dpy); - gl::Context *context = static_cast(ctx); - - if (!validateContext(display, context)) - { - return EGL_FALSE; - } + egl::Display *display = static_cast(dpy); + gl::Context *context = static_cast(ctx); - UNIMPLEMENTED(); // FIXME - - return egl::success(0); - } - catch(std::bad_alloc&) + if (!validateContext(display, context)) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return EGL_FALSE; } + + UNIMPLEMENTED(); // FIXME + + return egl::success(0); } EGLBoolean __stdcall eglWaitGL(void) { EVENT("()"); - try - { - UNIMPLEMENTED(); // FIXME + UNIMPLEMENTED(); // FIXME - return egl::success(0); - } - catch(std::bad_alloc&) - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); - } + return egl::success(0); } EGLBoolean __stdcall eglWaitNative(EGLint engine) { EVENT("(EGLint engine = %d)", engine); - try - { - UNIMPLEMENTED(); // FIXME + UNIMPLEMENTED(); // FIXME - return egl::success(0); - } - catch(std::bad_alloc&) - { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); - } + return egl::success(0); } EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface); - try - { - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = (egl::Surface*)surface; - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = (egl::Surface*)surface; - if (display->getRenderer()->isDeviceLost()) - { - return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); - } + if (!validateSurface(display, eglSurface)) + { + return EGL_FALSE; + } - if (surface == EGL_NO_SURFACE) - { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); - } + if (display->getRenderer()->isDeviceLost()) + { + return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); + } - if (eglSurface->swap()) - { - return egl::success(EGL_TRUE); - } + if (surface == EGL_NO_SURFACE) + { + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } - catch(std::bad_alloc&) + + if (eglSurface->swap()) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::success(EGL_TRUE); } return EGL_FALSE; @@ -1094,68 +945,54 @@ EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativ { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target); - try - { - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); - - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } - - if (display->getRenderer()->isDeviceLost()) - { - return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); - } - - UNIMPLEMENTED(); // FIXME + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = static_cast(surface); - return egl::success(0); + if (!validateSurface(display, eglSurface)) + { + return EGL_FALSE; } - catch(std::bad_alloc&) + + if (display->getRenderer()->isDeviceLost()) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); } + + UNIMPLEMENTED(); // FIXME + + return egl::success(0); } EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height) { EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height); - try + if (x < 0 || y < 0 || width < 0 || height < 0) { - if (x < 0 || y < 0 || width < 0 || height < 0) - { - return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); - } - - egl::Display *display = static_cast(dpy); - egl::Surface *eglSurface = static_cast(surface); + return egl::error(EGL_BAD_PARAMETER, EGL_FALSE); + } - if (!validateSurface(display, eglSurface)) - { - return EGL_FALSE; - } + egl::Display *display = static_cast(dpy); + egl::Surface *eglSurface = static_cast(surface); - if (display->getRenderer()->isDeviceLost()) - { - return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); - } + if (!validateSurface(display, eglSurface)) + { + return EGL_FALSE; + } - if (surface == EGL_NO_SURFACE) - { - return egl::error(EGL_BAD_SURFACE, EGL_FALSE); - } + if (display->getRenderer()->isDeviceLost()) + { + return egl::error(EGL_CONTEXT_LOST, EGL_FALSE); + } - if (eglSurface->postSubBuffer(x, y, width, height)) - { - return egl::success(EGL_TRUE); - } + if (surface == EGL_NO_SURFACE) + { + return egl::error(EGL_BAD_SURFACE, EGL_FALSE); } - catch(std::bad_alloc&) + + if (eglSurface->postSubBuffer(x, y, width, height)) { - return egl::error(EGL_BAD_ALLOC, EGL_FALSE); + return egl::success(EGL_TRUE); } return EGL_FALSE; @@ -1165,34 +1002,28 @@ __eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char { EVENT("(const char *procname = \"%s\")", procname); - try + struct Extension { - struct Extension - { - const char *name; - __eglMustCastToProperFunctionPointerType address; - }; + const char *name; + __eglMustCastToProperFunctionPointerType address; + }; - static const Extension eglExtensions[] = - { - {"eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE}, - {"eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV}, - {"", NULL}, - }; + static const Extension eglExtensions[] = + { + { "eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE }, + { "eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV }, + { "eglGetPlatformDisplayEXT", (__eglMustCastToProperFunctionPointerType)eglGetPlatformDisplayEXT }, + { "", NULL }, + }; - for (unsigned int ext = 0; ext < ArraySize(eglExtensions); ext++) + for (unsigned int ext = 0; ext < ArraySize(eglExtensions); ext++) + { + if (strcmp(procname, eglExtensions[ext].name) == 0) { - if (strcmp(procname, eglExtensions[ext].name) == 0) - { - return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address; - } + return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address; } - - return glGetProcAddress(procname); - } - catch(std::bad_alloc&) - { - return egl::error(EGL_BAD_ALLOC, (__eglMustCastToProperFunctionPointerType)NULL); } + + return glGetProcAddress(procname); } } diff --git a/src/3rdparty/angle/src/libEGL/libEGL.def b/src/3rdparty/angle/src/libEGL/libEGL.def index 71a5e67977..d7949d0354 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL.def +++ b/src/3rdparty/angle/src/libEGL/libEGL.def @@ -1,36 +1,41 @@ -LIBRARY libEGL +LIBRARY libEGL EXPORTS - eglBindAPI @14 - eglBindTexImage @20 - eglChooseConfig @7 - eglCopyBuffers @33 - eglCreateContext @23 - eglCreatePbufferFromClientBuffer @18 - eglCreatePbufferSurface @10 - eglCreatePixmapSurface @11 - eglCreateWindowSurface @9 - eglDestroyContext @24 - eglDestroySurface @12 - eglGetConfigAttrib @8 - eglGetConfigs @6 - eglGetCurrentContext @26 - eglGetCurrentDisplay @28 - eglGetCurrentSurface @27 - eglGetDisplay @2 - eglGetError @1 - eglGetProcAddress @34 - eglInitialize @3 - eglMakeCurrent @25 - eglQueryAPI @15 - eglQueryContext @29 - eglQueryString @5 - eglQuerySurface @13 - eglReleaseTexImage @21 - eglReleaseThread @17 - eglSurfaceAttrib @19 - eglSwapBuffers @32 - eglSwapInterval @22 - eglTerminate @4 - eglWaitClient @16 - eglWaitGL @30 - eglWaitNative @31 \ No newline at end of file + eglBindAPI @14 + eglBindTexImage @20 + eglChooseConfig @7 + eglCopyBuffers @33 + eglCreateContext @23 + eglCreatePbufferFromClientBuffer @18 + eglCreatePbufferSurface @10 + eglCreatePixmapSurface @11 + eglCreateWindowSurface @9 + eglDestroyContext @24 + eglDestroySurface @12 + eglGetConfigAttrib @8 + eglGetConfigs @6 + eglGetCurrentContext @26 + eglGetCurrentDisplay @28 + eglGetCurrentSurface @27 + eglGetDisplay @2 + eglGetError @1 + eglGetProcAddress @34 + eglInitialize @3 + eglMakeCurrent @25 + eglQueryAPI @15 + eglQueryContext @29 + eglQueryString @5 + eglQuerySurface @13 + eglReleaseTexImage @21 + eglReleaseThread @17 + eglSurfaceAttrib @19 + eglSwapBuffers @32 + eglSwapInterval @22 + eglTerminate @4 + eglWaitClient @16 + eglWaitGL @30 + eglWaitNative @31 + + ; Extensions + eglGetPlatformDisplayEXT @35 + eglQuerySurfacePointerANGLE @36 + eglPostSubBufferNV @37 diff --git a/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def b/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def index 8128e7c4f0..492ad4d0cf 100644 --- a/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def +++ b/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def @@ -1,36 +1,41 @@ LIBRARY libEGL EXPORTS - eglBindAPI@4 @14 - eglBindTexImage@12 @20 - eglChooseConfig@20 @7 - eglCopyBuffers@12 @33 - eglCreateContext@16 @23 - eglCreatePbufferFromClientBuffer@20 @18 - eglCreatePbufferSurface@12 @10 - eglCreatePixmapSurface@16 @11 - eglCreateWindowSurface@16 @9 - eglDestroyContext@8 @24 - eglDestroySurface@8 @12 - eglGetConfigAttrib@16 @8 - eglGetConfigs@16 @6 - eglGetCurrentContext@0 @26 - eglGetCurrentDisplay@0 @28 - eglGetCurrentSurface@4 @27 - eglGetDisplay@4 @2 - eglGetError@0 @1 - eglGetProcAddress@4 @34 - eglInitialize@12 @3 - eglMakeCurrent@16 @25 - eglQueryAPI@0 @15 - eglQueryContext@16 @29 - eglQueryString@8 @5 - eglQuerySurface@16 @13 - eglReleaseTexImage@12 @21 - eglReleaseThread@0 @17 - eglSurfaceAttrib@16 @19 - eglSwapBuffers@8 @32 - eglSwapInterval@8 @22 - eglTerminate@4 @4 - eglWaitClient@0 @16 - eglWaitGL@0 @30 - eglWaitNative@4 @31 + eglBindAPI@4 @14 + eglBindTexImage@12 @20 + eglChooseConfig@20 @7 + eglCopyBuffers@12 @33 + eglCreateContext@16 @23 + eglCreatePbufferFromClientBuffer@20 @18 + eglCreatePbufferSurface@12 @10 + eglCreatePixmapSurface@16 @11 + eglCreateWindowSurface@16 @9 + eglDestroyContext@8 @24 + eglDestroySurface@8 @12 + eglGetConfigAttrib@16 @8 + eglGetConfigs@16 @6 + eglGetCurrentContext@0 @26 + eglGetCurrentDisplay@0 @28 + eglGetCurrentSurface@4 @27 + eglGetDisplay@4 @2 + eglGetError@0 @1 + eglGetProcAddress@4 @34 + eglInitialize@12 @3 + eglMakeCurrent@16 @25 + eglQueryAPI@0 @15 + eglQueryContext@16 @29 + eglQueryString@8 @5 + eglQuerySurface@16 @13 + eglReleaseTexImage@12 @21 + eglReleaseThread@0 @17 + eglSurfaceAttrib@16 @19 + eglSwapBuffers@8 @32 + eglSwapInterval@8 @22 + eglTerminate@4 @4 + eglWaitClient@0 @16 + eglWaitGL@0 @30 + eglWaitNative@4 @31 + + ; Extensions + eglGetPlatformDisplayEXT@12 @35 + eglQuerySurfacePointerANGLE@16 @36 + eglPostSubBufferNV@24 @37 diff --git a/src/3rdparty/angle/src/libEGL/libEGLd.def b/src/3rdparty/angle/src/libEGL/libEGLd.def index 9317fce7de..0ebd27d0e1 100644 --- a/src/3rdparty/angle/src/libEGL/libEGLd.def +++ b/src/3rdparty/angle/src/libEGL/libEGLd.def @@ -1,36 +1,41 @@ -LIBRARY libEGLd +LIBRARY libEGLd EXPORTS - eglBindAPI @14 - eglBindTexImage @20 - eglChooseConfig @7 - eglCopyBuffers @33 - eglCreateContext @23 - eglCreatePbufferFromClientBuffer @18 - eglCreatePbufferSurface @10 - eglCreatePixmapSurface @11 - eglCreateWindowSurface @9 - eglDestroyContext @24 - eglDestroySurface @12 - eglGetConfigAttrib @8 - eglGetConfigs @6 - eglGetCurrentContext @26 - eglGetCurrentDisplay @28 - eglGetCurrentSurface @27 - eglGetDisplay @2 - eglGetError @1 - eglGetProcAddress @34 - eglInitialize @3 - eglMakeCurrent @25 - eglQueryAPI @15 - eglQueryContext @29 - eglQueryString @5 - eglQuerySurface @13 - eglReleaseTexImage @21 - eglReleaseThread @17 - eglSurfaceAttrib @19 - eglSwapBuffers @32 - eglSwapInterval @22 - eglTerminate @4 - eglWaitClient @16 - eglWaitGL @30 - eglWaitNative @31 + eglBindAPI @14 + eglBindTexImage @20 + eglChooseConfig @7 + eglCopyBuffers @33 + eglCreateContext @23 + eglCreatePbufferFromClientBuffer @18 + eglCreatePbufferSurface @10 + eglCreatePixmapSurface @11 + eglCreateWindowSurface @9 + eglDestroyContext @24 + eglDestroySurface @12 + eglGetConfigAttrib @8 + eglGetConfigs @6 + eglGetCurrentContext @26 + eglGetCurrentDisplay @28 + eglGetCurrentSurface @27 + eglGetDisplay @2 + eglGetError @1 + eglGetProcAddress @34 + eglInitialize @3 + eglMakeCurrent @25 + eglQueryAPI @15 + eglQueryContext @29 + eglQueryString @5 + eglQuerySurface @13 + eglReleaseTexImage @21 + eglReleaseThread @17 + eglSurfaceAttrib @19 + eglSwapBuffers @32 + eglSwapInterval @22 + eglTerminate @4 + eglWaitClient @16 + eglWaitGL @30 + eglWaitNative @31 + + ; Extensions + eglGetPlatformDisplayEXT @35 + eglQuerySurfacePointerANGLE @36 + eglPostSubBufferNV @37 diff --git a/src/3rdparty/angle/src/libEGL/libEGLd_mingw32.def b/src/3rdparty/angle/src/libEGL/libEGLd_mingw32.def index 1c72413f89..ab0320dc0d 100644 --- a/src/3rdparty/angle/src/libEGL/libEGLd_mingw32.def +++ b/src/3rdparty/angle/src/libEGL/libEGLd_mingw32.def @@ -1,36 +1,41 @@ LIBRARY libEGLd EXPORTS - eglBindAPI@4 @14 - eglBindTexImage@12 @20 - eglChooseConfig@20 @7 - eglCopyBuffers@12 @33 - eglCreateContext@16 @23 - eglCreatePbufferFromClientBuffer@20 @18 - eglCreatePbufferSurface@12 @10 - eglCreatePixmapSurface@16 @11 - eglCreateWindowSurface@16 @9 - eglDestroyContext@8 @24 - eglDestroySurface@8 @12 - eglGetConfigAttrib@16 @8 - eglGetConfigs@16 @6 - eglGetCurrentContext@0 @26 - eglGetCurrentDisplay@0 @28 - eglGetCurrentSurface@4 @27 - eglGetDisplay@4 @2 - eglGetError@0 @1 - eglGetProcAddress@4 @34 - eglInitialize@12 @3 - eglMakeCurrent@16 @25 - eglQueryAPI@0 @15 - eglQueryContext@16 @29 - eglQueryString@8 @5 - eglQuerySurface@16 @13 - eglReleaseTexImage@12 @21 - eglReleaseThread@0 @17 - eglSurfaceAttrib@16 @19 - eglSwapBuffers@8 @32 - eglSwapInterval@8 @22 - eglTerminate@4 @4 - eglWaitClient@0 @16 - eglWaitGL@0 @30 - eglWaitNative@4 @31 + eglBindAPI@4 @14 + eglBindTexImage@12 @20 + eglChooseConfig@20 @7 + eglCopyBuffers@12 @33 + eglCreateContext@16 @23 + eglCreatePbufferFromClientBuffer@20 @18 + eglCreatePbufferSurface@12 @10 + eglCreatePixmapSurface@16 @11 + eglCreateWindowSurface@16 @9 + eglDestroyContext@8 @24 + eglDestroySurface@8 @12 + eglGetConfigAttrib@16 @8 + eglGetConfigs@16 @6 + eglGetCurrentContext@0 @26 + eglGetCurrentDisplay@0 @28 + eglGetCurrentSurface@4 @27 + eglGetDisplay@4 @2 + eglGetError@0 @1 + eglGetProcAddress@4 @34 + eglInitialize@12 @3 + eglMakeCurrent@16 @25 + eglQueryAPI@0 @15 + eglQueryContext@16 @29 + eglQueryString@8 @5 + eglQuerySurface@16 @13 + eglReleaseTexImage@12 @21 + eglReleaseThread@0 @17 + eglSurfaceAttrib@16 @19 + eglSwapBuffers@8 @32 + eglSwapInterval@8 @22 + eglTerminate@4 @4 + eglWaitClient@0 @16 + eglWaitGL@0 @30 + eglWaitNative@4 @31 + + ; Extensions + eglGetPlatformDisplayEXT@12 @35 + eglQuerySurfacePointerANGLE@16 @36 + eglPostSubBufferNV@24 @37 diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp index 4cdf5f0362..5788af7827 100644 --- a/src/3rdparty/angle/src/libEGL/main.cpp +++ b/src/3rdparty/angle/src/libEGL/main.cpp @@ -1,4 +1,3 @@ -#include "../libGLESv2/precompiled.h" // // Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be @@ -10,61 +9,57 @@ #include "libEGL/main.h" #include "common/debug.h" +#include "common/tls.h" -#if !defined(ANGLE_OS_WINRT) -static DWORD currentTLS = TLS_OUT_OF_INDEXES; -#else -static __declspec(thread) void *currentTLS = 0; +#if defined(ANGLE_PLATFORM_WINRT) +__declspec(thread) #endif +static TLSIndex currentTLS = TLS_OUT_OF_INDEXES; namespace egl { Current *AllocateCurrent() { -#if !defined(ANGLE_OS_WINRT) - Current *current = (egl::Current*)LocalAlloc(LPTR, sizeof(egl::Current)); -#else - currentTLS = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Current)); - Current *current = (egl::Current*)currentTLS; +#if defined(ANGLE_PLATFORM_WINRT) + if (currentTLS == TLS_OUT_OF_INDEXES) + { + currentTLS = CreateTLSIndex(); + } #endif - - if (!current) + ASSERT(currentTLS != TLS_OUT_OF_INDEXES); + if (currentTLS == TLS_OUT_OF_INDEXES) { - ERR("Could not allocate thread local storage."); return NULL; } -#if !defined(ANGLE_OS_WINRT) - ASSERT(currentTLS != TLS_OUT_OF_INDEXES); - TlsSetValue(currentTLS, current); -#endif - + Current *current = new Current(); current->error = EGL_SUCCESS; current->API = EGL_OPENGL_ES_API; current->display = EGL_NO_DISPLAY; current->drawSurface = EGL_NO_SURFACE; current->readSurface = EGL_NO_SURFACE; + if (!SetTLSValue(currentTLS, current)) + { + ERR("Could not set thread local storage."); + return NULL; + } + return current; } void DeallocateCurrent() { -#if !defined(ANGLE_OS_WINRT) - void *current = TlsGetValue(currentTLS); - - if (current) +#if defined(ANGLE_PLATFORM_WINRT) + if (currentTLS == TLS_OUT_OF_INDEXES) { - LocalFree((HLOCAL)current); - } -#else - if (currentTLS) - { - HeapFree(GetProcessHeap(), 0, currentTLS); - currentTLS = 0; + return; } #endif + Current *current = reinterpret_cast(GetTLSValue(currentTLS)); + SafeDelete(current); + SetTLSValue(currentTLS, NULL); } } @@ -91,16 +86,18 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved } } #endif -#if !defined(ANGLE_OS_WINRT) - currentTLS = TlsAlloc(); +#if defined(ANGLE_PLATFORM_WINRT) // On WinRT, don't handle TLS from DllMain + return DisableThreadLibraryCalls(instance); +#endif + + currentTLS = CreateTLSIndex(); if (currentTLS == TLS_OUT_OF_INDEXES) { return FALSE; } -#endif } - // Fall throught to initialize index + // Fall through to initialize index case DLL_THREAD_ATTACH: { egl::AllocateCurrent(); @@ -113,9 +110,9 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved break; case DLL_PROCESS_DETACH: { +#if !defined(ANGLE_PLATFORM_WINRT) egl::DeallocateCurrent(); -#if !defined(ANGLE_OS_WINRT) - TlsFree(currentTLS); + DestroyTLSIndex(currentTLS); #endif } break; @@ -134,20 +131,16 @@ namespace egl Current *GetCurrentData() { #ifndef QT_OPENGL_ES_2_ANGLE_STATIC -#if !defined(ANGLE_OS_WINRT) - Current *current = (Current*)TlsGetValue(currentTLS); -#else - Current *current = (Current*)currentTLS; -#endif -#else - // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. - static Current s_current = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; - Current *current = &s_current; -#endif + Current *current = reinterpret_cast(GetTLSValue(currentTLS)); // ANGLE issue 488: when the dll is loaded after thread initialization, // thread local storage (current) might not exist yet. return (current ? current : AllocateCurrent()); +#else + // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. + static Current current = { EGL_SUCCESS, EGL_OPENGL_ES_API, EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE }; + return ¤t; +#endif } void setCurrentError(EGLint error) diff --git a/src/3rdparty/angle/src/libEGL/main.h b/src/3rdparty/angle/src/libEGL/main.h index 77da8f0f8e..6030fb6ad9 100644 --- a/src/3rdparty/angle/src/libEGL/main.h +++ b/src/3rdparty/angle/src/libEGL/main.h @@ -9,6 +9,7 @@ #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 21c2f86ce8..1cbfc6751d 100644 --- a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h +++ b/src/3rdparty/angle/src/libGLESv2/BinaryStream.h @@ -10,6 +10,7 @@ #define LIBGLESV2_BINARYSTREAM_H_ #include "common/angleutils.h" +#include "common/mathutil.h" namespace gl { @@ -25,42 +26,49 @@ class BinaryInputStream mLength = length; } - template - void read(T *v, size_t num) + // readInt will generate an error for bool types + template + IntT readInt() { - union - { - T dummy; // Compilation error for non-trivial types - } dummy; - (void) dummy; + int value; + read(&value); + return static_cast(value); + } - if (mError) - { - return; - } + template + void readInt(IntT *outValue) + { + *outValue = readInt(); + } - size_t length = num * sizeof(T); + bool readBool() + { + int value; + read(&value); + return (value > 0); + } - if (mOffset + length > mLength) - { - mError = true; - return; - } + void readBool(bool *outValue) + { + *outValue = readBool(); + } - memcpy(v, mData + mOffset, length); - mOffset += length; + void readBytes(unsigned char outArray[], size_t count) + { + read(outArray, count); } - template - void read(T * v) + std::string readString() { - read(v, 1); + std::string outString; + readString(&outString); + return outString; } - void read(std::string *v) + void readString(std::string *v) { size_t length; - read(&length); + readInt(&length); if (mError) { @@ -109,6 +117,30 @@ class BinaryInputStream size_t mOffset; const char *mData; size_t mLength; + + template + void read(T *v, size_t num) + { + META_ASSERT(std::is_fundamental::value); + + size_t length = num * sizeof(T); + + if (mOffset + length > mLength) + { + mError = true; + return; + } + + memcpy(v, mData + mOffset, length); + mOffset += length; + } + + template + void read(T *v) + { + read(v, 1); + } + }; class BinaryOutputStream @@ -118,31 +150,24 @@ class BinaryOutputStream { } - template - void write(const T *v, size_t num) + // writeInt also handles bool types + template + void writeInt(IntT param) { - union - { - T dummy; // Compilation error for non-trivial types - } dummy; - (void) dummy; - - const char *asBytes = reinterpret_cast(v); - mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T)); + ASSERT(rx::IsIntegerCastSafe(param)); + int intValue = static_cast(param); + write(&intValue, 1); } - template - void write(const T &v) + void writeString(const std::string &v) { - write(&v, 1); + writeInt(v.length()); + write(v.c_str(), v.length()); } - void write(const std::string &v) + void writeBytes(const unsigned char *bytes, size_t count) { - size_t length = v.length(); - write(length); - - write(v.c_str(), length); + write(bytes, count); } size_t length() const @@ -158,6 +183,15 @@ class BinaryOutputStream private: DISALLOW_COPY_AND_ASSIGN(BinaryOutputStream); std::vector mData; + + template + void write(const T *v, size_t num) + { + META_ASSERT(std::is_fundamental::value); + const char *asBytes = reinterpret_cast(v); + mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T)); + } + }; } diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp index c007d5d9e9..a47b8f402f 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Buffer.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" // -// Copyright (c) 2002-2013 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,117 +10,80 @@ // [OpenGL ES 2.0.24] section 2.9 page 21. #include "libGLESv2/Buffer.h" - -#include "libGLESv2/renderer/VertexBuffer.h" -#include "libGLESv2/renderer/IndexBuffer.h" -#include "libGLESv2/renderer/BufferStorage.h" +#include "libGLESv2/renderer/BufferImpl.h" #include "libGLESv2/renderer/Renderer.h" namespace gl { -Buffer::Buffer(rx::Renderer *renderer, GLuint id) : RefCountObject(id) +Buffer::Buffer(rx::BufferImpl *impl, GLuint id) + : RefCountObject(id), + mBuffer(impl), + mUsage(GL_DYNAMIC_DRAW), + mSize(0), + mAccessFlags(0), + mMapped(GL_FALSE), + mMapPointer(NULL), + mMapOffset(0), + mMapLength(0) { - mRenderer = renderer; - mUsage = GL_DYNAMIC_DRAW; - - mBufferStorage = renderer->createBufferStorage(); - mStaticVertexBuffer = NULL; - mStaticIndexBuffer = NULL; - mUnmodifiedDataUse = 0; } Buffer::~Buffer() { - delete mBufferStorage; - delete mStaticVertexBuffer; - delete mStaticIndexBuffer; + delete mBuffer; } void Buffer::bufferData(const void *data, GLsizeiptr size, GLenum usage) { - mBufferStorage->clear(); - mIndexRangeCache.clear(); - mBufferStorage->setData(data, size, 0); - mUsage = usage; - - invalidateStaticData(); - - if (usage == GL_STATIC_DRAW) - { - mStaticVertexBuffer = new rx::StaticVertexBufferInterface(mRenderer); - mStaticIndexBuffer = new rx::StaticIndexBufferInterface(mRenderer); - } + mSize = size; + mBuffer->setData(data, size, usage); } void Buffer::bufferSubData(const void *data, GLsizeiptr size, GLintptr offset) { - mBufferStorage->setData(data, size, offset); - mIndexRangeCache.invalidateRange(offset, size); - - if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)) - { - invalidateStaticData(); - } - - mUnmodifiedDataUse = 0; + mBuffer->setSubData(data, size, offset); } -rx::BufferStorage *Buffer::getStorage() const +void Buffer::copyBufferSubData(Buffer* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) { - return mBufferStorage; + mBuffer->copySubData(source->getImplementation(), size, sourceOffset, destOffset); } -unsigned int Buffer::size() const +GLvoid *Buffer::mapRange(GLintptr offset, GLsizeiptr length, GLbitfield access) { - return mBufferStorage->getSize(); -} + ASSERT(!mMapped); + ASSERT(offset + length <= mSize); -GLenum Buffer::usage() const -{ - return mUsage; -} + void *dataPointer = mBuffer->map(offset, length, access); -rx::StaticVertexBufferInterface *Buffer::getStaticVertexBuffer() -{ - return mStaticVertexBuffer; -} + mMapped = GL_TRUE; + mMapPointer = static_cast(static_cast(dataPointer)); + mMapOffset = static_cast(offset); + mMapLength = static_cast(length); + mAccessFlags = static_cast(access); -rx::StaticIndexBufferInterface *Buffer::getStaticIndexBuffer() -{ - return mStaticIndexBuffer; + return mMapPointer; } -void Buffer::invalidateStaticData() +void Buffer::unmap() { - delete mStaticVertexBuffer; - mStaticVertexBuffer = NULL; - - delete mStaticIndexBuffer; - mStaticIndexBuffer = NULL; + ASSERT(mMapped); - mUnmodifiedDataUse = 0; -} + mBuffer->unmap(); -// Creates static buffers if sufficient used data has been left unmodified -void Buffer::promoteStaticUsage(int dataSize) -{ - if (!mStaticVertexBuffer && !mStaticIndexBuffer) - { - mUnmodifiedDataUse += dataSize; - - if (mUnmodifiedDataUse > 3 * mBufferStorage->getSize()) - { - mStaticVertexBuffer = new rx::StaticVertexBufferInterface(mRenderer); - mStaticIndexBuffer = new rx::StaticIndexBufferInterface(mRenderer); - } - } + mMapped = GL_FALSE; + mMapPointer = NULL; + mMapOffset = 0; + mMapLength = 0; + mAccessFlags = 0; } -rx::IndexRangeCache *Buffer::getIndexRangeCache() +void Buffer::markTransformFeedbackUsage() { - return &mIndexRangeCache; + // TODO: Only used by the DX11 backend. Refactor to a more appropriate place. + mBuffer->markTransformFeedbackUsage(); } } diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.h b/src/3rdparty/angle/src/libGLESv2/Buffer.h index 4048f4b906..389c3d4b00 100644 --- a/src/3rdparty/angle/src/libGLESv2/Buffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Buffer.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2013 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. // @@ -13,14 +13,11 @@ #include "common/angleutils.h" #include "common/RefCountObject.h" -#include "libGLESv2/renderer/IndexRangeCache.h" namespace rx { class Renderer; -class BufferStorage; -class StaticIndexBufferInterface; -class StaticVertexBufferInterface; +class BufferImpl; }; namespace gl @@ -29,38 +26,40 @@ namespace gl class Buffer : public RefCountObject { public: - Buffer(rx::Renderer *renderer, GLuint id); + Buffer(rx::BufferImpl *impl, GLuint id); 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(); - GLenum usage() const; + GLenum getUsage() const { return mUsage; } + GLint getAccessFlags() const { return mAccessFlags; } + GLboolean isMapped() const { return mMapped; } + GLvoid *getMapPointer() const { return mMapPointer; } + GLint64 getMapOffset() const { return mMapOffset; } + GLint64 getMapLength() const { return mMapLength; } + GLint64 getSize() const { return mSize; } - rx::BufferStorage *getStorage() const; - unsigned int size() const; + rx::BufferImpl *getImplementation() const { return mBuffer; } - rx::StaticVertexBufferInterface *getStaticVertexBuffer(); - rx::StaticIndexBufferInterface *getStaticIndexBuffer(); - void invalidateStaticData(); - void promoteStaticUsage(int dataSize); - - rx::IndexRangeCache *getIndexRangeCache(); + void markTransformFeedbackUsage(); private: DISALLOW_COPY_AND_ASSIGN(Buffer); - rx::Renderer *mRenderer; - GLenum mUsage; - - rx::BufferStorage *mBufferStorage; + rx::BufferImpl *mBuffer; - rx::IndexRangeCache mIndexRangeCache; - - rx::StaticVertexBufferInterface *mStaticVertexBuffer; - rx::StaticIndexBufferInterface *mStaticIndexBuffer; - unsigned int mUnmodifiedDataUse; + GLenum mUsage; + GLsizeiptr mSize; + GLint mAccessFlags; + GLboolean mMapped; + GLvoid *mMapPointer; + GLint64 mMapOffset; + GLint64 mMapLength; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/Caps.cpp b/src/3rdparty/angle/src/libGLESv2/Caps.cpp new file mode 100644 index 0000000000..c1c4dc9ee7 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/Caps.cpp @@ -0,0 +1,363 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "libGLESv2/Caps.h" +#include "common/debug.h" +#include "common/angleutils.h" + +#include "angle_gl.h" + +#include +#include + +namespace gl +{ + +TextureCaps::TextureCaps() + : texturable(false), + filterable(false), + renderable(false), + sampleCounts() +{ +} + +void TextureCapsMap::insert(GLenum internalFormat, const TextureCaps &caps) +{ + mCapsMap.insert(std::make_pair(internalFormat, caps)); +} + +void TextureCapsMap::remove(GLenum internalFormat) +{ + InternalFormatToCapsMap::iterator i = mCapsMap.find(internalFormat); + if (i != mCapsMap.end()) + { + mCapsMap.erase(i); + } +} + +const TextureCaps &TextureCapsMap::get(GLenum internalFormat) const +{ + static TextureCaps defaultUnsupportedTexture; + InternalFormatToCapsMap::const_iterator iter = mCapsMap.find(internalFormat); + return (iter != mCapsMap.end()) ? iter->second : defaultUnsupportedTexture; +} + +TextureCapsMap::const_iterator TextureCapsMap::begin() const +{ + return mCapsMap.begin(); +} + +TextureCapsMap::const_iterator TextureCapsMap::end() const +{ + return mCapsMap.end(); +} + +size_t TextureCapsMap::size() const +{ + return mCapsMap.size(); +} + +Extensions::Extensions() + : elementIndexUint(false), + packedDepthStencil(false), + getProgramBinary(false), + rgb8rgba8(false), + textureFormatBGRA8888(false), + readFormatBGRA(false), + pixelBufferObject(false), + mapBuffer(false), + mapBufferRange(false), + textureHalfFloat(false), + textureHalfFloatLinear(false), + textureFloat(false), + textureFloatLinear(false), + textureRG(false), + textureCompressionDXT1(false), + textureCompressionDXT3(false), + textureCompressionDXT5(false), + depthTextures(false), + textureNPOT(false), + drawBuffers(false), + textureStorage(false), + textureFilterAnisotropic(false), + maxTextureAnisotropy(false), + occlusionQueryBoolean(false), + fence(false), + timerQuery(false), + robustness(false), + blendMinMax(false), + framebufferBlit(false), + framebufferMultisample(false), + instancedArrays(false), + packReverseRowOrder(false), + standardDerivatives(false), + shaderTextureLOD(false), + fragDepth(false), + textureUsage(false), + translatedShaderSource(false), + colorBufferFloat(false) +{ +} + +static void InsertExtensionString(const std::string &extension, bool supported, std::vector *extensionVector) +{ + if (supported) + { + extensionVector->push_back(extension); + } +} + +std::vector Extensions::getStrings() const +{ + std::vector extensionStrings; + + // | Extension name | Supported flag | Output vector | + InsertExtensionString("GL_OES_element_index_uint", elementIndexUint, &extensionStrings); + InsertExtensionString("GL_OES_packed_depth_stencil", packedDepthStencil, &extensionStrings); + InsertExtensionString("GL_OES_get_program_binary", getProgramBinary, &extensionStrings); + InsertExtensionString("GL_OES_rgb8_rgba8", rgb8rgba8, &extensionStrings); + InsertExtensionString("GL_EXT_texture_format_BGRA8888", textureFormatBGRA8888, &extensionStrings); + InsertExtensionString("GL_EXT_read_format_bgra", readFormatBGRA, &extensionStrings); + InsertExtensionString("GL_NV_pixel_buffer_object", pixelBufferObject, &extensionStrings); + InsertExtensionString("GL_OES_mapbuffer", mapBuffer, &extensionStrings); + InsertExtensionString("GL_EXT_map_buffer_range", mapBufferRange, &extensionStrings); + InsertExtensionString("GL_OES_texture_half_float", textureHalfFloat, &extensionStrings); + InsertExtensionString("GL_OES_texture_half_float_linear", textureHalfFloatLinear, &extensionStrings); + InsertExtensionString("GL_OES_texture_float", textureFloat, &extensionStrings); + InsertExtensionString("GL_OES_texture_float_linear", textureFloatLinear, &extensionStrings); + InsertExtensionString("GL_EXT_texture_rg", textureRG, &extensionStrings); + InsertExtensionString("GL_EXT_texture_compression_dxt1", textureCompressionDXT1, &extensionStrings); + InsertExtensionString("GL_ANGLE_texture_compression_dxt3", textureCompressionDXT3, &extensionStrings); + InsertExtensionString("GL_ANGLE_texture_compression_dxt5", textureCompressionDXT5, &extensionStrings); + InsertExtensionString("GL_EXT_sRGB", sRGB, &extensionStrings); + InsertExtensionString("GL_ANGLE_depth_texture", depthTextures, &extensionStrings); + InsertExtensionString("GL_EXT_texture_storage", textureStorage, &extensionStrings); + InsertExtensionString("GL_OES_texture_npot", textureNPOT, &extensionStrings); + InsertExtensionString("GL_EXT_draw_buffers", drawBuffers, &extensionStrings); + InsertExtensionString("GL_EXT_texture_filter_anisotropic", textureFilterAnisotropic, &extensionStrings); + InsertExtensionString("GL_EXT_occlusion_query_boolean", occlusionQueryBoolean, &extensionStrings); + InsertExtensionString("GL_NV_fence", fence, &extensionStrings); + InsertExtensionString("GL_ANGLE_timer_query", timerQuery, &extensionStrings); + InsertExtensionString("GL_EXT_robustness", robustness, &extensionStrings); + InsertExtensionString("GL_EXT_blend_minmax", blendMinMax, &extensionStrings); + InsertExtensionString("GL_ANGLE_framebuffer_blit", framebufferBlit, &extensionStrings); + InsertExtensionString("GL_ANGLE_framebuffer_multisample", framebufferMultisample, &extensionStrings); + InsertExtensionString("GL_ANGLE_instanced_arrays", instancedArrays, &extensionStrings); + InsertExtensionString("GL_ANGLE_pack_reverse_row_order", packReverseRowOrder, &extensionStrings); + InsertExtensionString("GL_OES_standard_derivatives", standardDerivatives, &extensionStrings); + InsertExtensionString("GL_EXT_shader_texture_lod", shaderTextureLOD, &extensionStrings); + InsertExtensionString("GL_EXT_frag_depth", fragDepth, &extensionStrings); + InsertExtensionString("GL_ANGLE_texture_usage", textureUsage, &extensionStrings); + InsertExtensionString("GL_ANGLE_translated_shader_source", translatedShaderSource, &extensionStrings); + InsertExtensionString("GL_EXT_color_buffer_float", colorBufferFloat, &extensionStrings); + + return extensionStrings; +} + +static bool GetFormatSupport(const TextureCapsMap &textureCaps, const std::vector &requiredFormats, + bool requiresFiltering, bool requiresRendering) +{ + for (size_t i = 0; i < requiredFormats.size(); i++) + { + const TextureCaps &cap = textureCaps.get(requiredFormats[i]); + + if (requiresFiltering && !cap.filterable) + { + return false; + } + + if (requiresRendering && !cap.renderable) + { + return false; + } + } + + return true; +} + +// Checks for GL_OES_rgb8_rgba8 support +static bool DetermineRGB8AndRGBA8TextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_RGB8); + requiredFormats.push_back(GL_RGBA8); + + return GetFormatSupport(textureCaps, requiredFormats, true, true); +} + +// Checks for GL_EXT_texture_format_BGRA8888 support +static bool DetermineBGRA8TextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_BGRA8_EXT); + + return GetFormatSupport(textureCaps, requiredFormats, true, true); +} + +// Checks for GL_OES_texture_half_float support +static bool DetermineHalfFloatTextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_RGB16F); + requiredFormats.push_back(GL_RGBA16F); + + return GetFormatSupport(textureCaps, requiredFormats, false, true); +} + +// Checks for GL_OES_texture_half_float_linear support +static bool DetermineHalfFloatTextureFilteringSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_RGB16F); + requiredFormats.push_back(GL_RGBA16F); + + return GetFormatSupport(textureCaps, requiredFormats, true, false); +} + +// Checks for GL_OES_texture_float support +static bool DetermineFloatTextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_RGB32F); + requiredFormats.push_back(GL_RGBA32F); + + return GetFormatSupport(textureCaps, requiredFormats, false, true); +} + +// Checks for GL_OES_texture_float_linear support +static bool DetermineFloatTextureFilteringSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_RGB32F); + requiredFormats.push_back(GL_RGBA32F); + + return GetFormatSupport(textureCaps, requiredFormats, true, false); +} + +// Checks for GL_EXT_texture_rg support +static bool DetermineRGTextureSupport(const TextureCapsMap &textureCaps, bool checkHalfFloatFormats, bool checkFloatFormats) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_R8); + requiredFormats.push_back(GL_RG8); + if (checkHalfFloatFormats) + { + requiredFormats.push_back(GL_R16F); + requiredFormats.push_back(GL_RG16F); + } + if (checkFloatFormats) + { + requiredFormats.push_back(GL_R32F); + requiredFormats.push_back(GL_RG32F); + } + + return GetFormatSupport(textureCaps, requiredFormats, true, false); +} + +// Check for GL_EXT_texture_compression_dxt1 +static bool DetermineDXT1TextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_COMPRESSED_RGB_S3TC_DXT1_EXT); + requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT); + + return GetFormatSupport(textureCaps, requiredFormats, true, false); +} + +// Check for GL_ANGLE_texture_compression_dxt3 +static bool DetermineDXT3TextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); + + return GetFormatSupport(textureCaps, requiredFormats, true, false); +} + +// Check for GL_ANGLE_texture_compression_dxt5 +static bool DetermineDXT5TextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); + + return GetFormatSupport(textureCaps, requiredFormats, true, false); +} + +// Check for GL_ANGLE_texture_compression_dxt5 +static bool DetermineSRGBTextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFilterFormats; + requiredFilterFormats.push_back(GL_SRGB8); + requiredFilterFormats.push_back(GL_SRGB8_ALPHA8); + + std::vector requiredRenderFormats; + requiredRenderFormats.push_back(GL_SRGB8_ALPHA8); + + return GetFormatSupport(textureCaps, requiredFilterFormats, true, false) && + GetFormatSupport(textureCaps, requiredRenderFormats, false, true); +} + +// Check for GL_ANGLE_depth_texture +static bool DetermineDepthTextureSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_DEPTH_COMPONENT16); + requiredFormats.push_back(GL_DEPTH_COMPONENT32_OES); + requiredFormats.push_back(GL_DEPTH24_STENCIL8_OES); + + return GetFormatSupport(textureCaps, requiredFormats, true, true); +} + +// Check for GL_EXT_color_buffer_float +static bool DetermineColorBufferFloatSupport(const TextureCapsMap &textureCaps) +{ + std::vector requiredFormats; + requiredFormats.push_back(GL_R16F); + requiredFormats.push_back(GL_RG16F); + requiredFormats.push_back(GL_RGBA16F); + requiredFormats.push_back(GL_R32F); + requiredFormats.push_back(GL_RG32F); + requiredFormats.push_back(GL_RGBA32F); + requiredFormats.push_back(GL_R11F_G11F_B10F); + + return GetFormatSupport(textureCaps, requiredFormats, false, true); +} + +void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps) +{ + rgb8rgba8 = DetermineRGB8AndRGBA8TextureSupport(textureCaps); + textureFormatBGRA8888 = DetermineBGRA8TextureSupport(textureCaps); + textureHalfFloat = DetermineHalfFloatTextureSupport(textureCaps); + textureHalfFloatLinear = DetermineHalfFloatTextureFilteringSupport(textureCaps); + textureFloat = DetermineFloatTextureSupport(textureCaps); + textureFloatLinear = DetermineFloatTextureFilteringSupport(textureCaps); + textureRG = DetermineRGTextureSupport(textureCaps, textureHalfFloat, textureFloat); + textureCompressionDXT1 = DetermineDXT1TextureSupport(textureCaps); + textureCompressionDXT3 = DetermineDXT3TextureSupport(textureCaps); + textureCompressionDXT5 = DetermineDXT5TextureSupport(textureCaps); + sRGB = DetermineSRGBTextureSupport(textureCaps); + depthTextures = DetermineDepthTextureSupport(textureCaps); + colorBufferFloat = DetermineColorBufferFloatSupport(textureCaps); +} + +Caps::Caps() + : maxElementIndex(0), + max3DTextureSize(0), + max2DTextureSize(0), + maxArrayTextureLayers(0), + maxLODBias(0), + maxCubeMapTextureSize(0), + maxRenderbufferSize(0), + maxDrawBuffers(0), + maxColorAttachments(0), + maxViewportWidth(0), + maxViewportHeight(0), + minAliasedPointSize(0), + maxAliasedPointSize(0), + minAliasedLineWidth(0) +{ +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/Caps.h b/src/3rdparty/angle/src/libGLESv2/Caps.h new file mode 100644 index 0000000000..a08618ec9c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/Caps.h @@ -0,0 +1,222 @@ +#ifndef LIBGLESV2_CAPS_H +#define LIBGLESV2_CAPS_H + +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "angle_gl.h" + +#include +#include +#include +#include + +namespace gl +{ + +struct TextureCaps +{ + TextureCaps(); + + // Supports for basic texturing: glTexImage, glTexSubImage, etc + bool texturable; + + // Support for linear or anisotropic filtering + bool filterable; + + // Support for being used as a framebuffer attachment or renderbuffer format + bool renderable; + + std::set sampleCounts; +}; + +class TextureCapsMap +{ + public: + typedef std::unordered_map::const_iterator const_iterator; + + void insert(GLenum internalFormat, const TextureCaps &caps); + void remove(GLenum internalFormat); + + const TextureCaps &get(GLenum internalFormat) const; + + const_iterator begin() const; + const_iterator end() const; + + size_t size() const; + + private: + typedef std::unordered_map InternalFormatToCapsMap; + InternalFormatToCapsMap mCapsMap; +}; + +struct Extensions +{ + Extensions(); + + // Generate a vector of supported extension strings + std::vector getStrings() const; + + // Set all texture related extension support based on the supported textures. + // Determines support for: + // GL_OES_rgb8_rgba8 + // GL_EXT_texture_format_BGRA8888 + // GL_OES_texture_half_float, GL_OES_texture_half_float_linear + // GL_OES_texture_float, GL_OES_texture_float_linear + // GL_EXT_texture_rg + // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3, GL_ANGLE_texture_compression_dxt5 + // GL_ANGLE_depth_texture + // GL_EXT_color_buffer_float + void setTextureExtensionSupport(const TextureCapsMap &textureCaps); + + // ES2 Extension support + + // GL_OES_element_index_uint + bool elementIndexUint; + + // GL_OES_packed_depth_stencil + bool packedDepthStencil; + + // GL_OES_get_program_binary + bool getProgramBinary; + + // GL_OES_rgb8_rgba8 + // Implies that TextureCaps for GL_RGB8 and GL_RGBA8 exist + bool rgb8rgba8; + + // GL_EXT_texture_format_BGRA8888 + // Implies that TextureCaps for GL_BGRA8 exist + bool textureFormatBGRA8888; + + // GL_EXT_read_format_bgra + bool readFormatBGRA; + + // GL_NV_pixel_buffer_object + bool pixelBufferObject; + + // GL_OES_mapbuffer and GL_EXT_map_buffer_range + bool mapBuffer; + bool mapBufferRange; + + // GL_OES_texture_half_float and GL_OES_texture_half_float_linear + // Implies that TextureCaps for GL_RGB16F, GL_RGBA16F, GL_ALPHA32F_EXT, GL_LUMINANCE32F_EXT and + // GL_LUMINANCE_ALPHA32F_EXT exist + bool textureHalfFloat; + bool textureHalfFloatLinear; + + // GL_OES_texture_float and GL_OES_texture_float_linear + // Implies that TextureCaps for GL_RGB32F, GL_RGBA32F, GL_ALPHA16F_EXT, GL_LUMINANCE16F_EXT and + // GL_LUMINANCE_ALPHA16F_EXT exist + bool textureFloat; + bool textureFloatLinear; + + // GL_EXT_texture_rg + // Implies that TextureCaps for GL_R8, GL_RG8 (and floating point R/RG texture formats if floating point extensions + // are also present) exist + bool textureRG; + + // GL_EXT_texture_compression_dxt1, GL_ANGLE_texture_compression_dxt3 and GL_ANGLE_texture_compression_dxt5 + // Implies that TextureCaps for GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT + // GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE and GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE + bool textureCompressionDXT1; + bool textureCompressionDXT3; + bool textureCompressionDXT5; + + // GL_EXT_sRGB + // Implies that TextureCaps for GL_SRGB8_ALPHA8 and GL_SRGB8 exist + // TODO: Don't advertise this extension in ES3 + bool sRGB; + + // GL_ANGLE_depth_texture + bool depthTextures; + + // GL_EXT_texture_storage + bool textureStorage; + + // GL_OES_texture_npot + bool textureNPOT; + + // GL_EXT_draw_buffers + bool drawBuffers; + + // GL_EXT_texture_filter_anisotropic + bool textureFilterAnisotropic; + GLfloat maxTextureAnisotropy; + + // GL_EXT_occlusion_query_boolean + bool occlusionQueryBoolean; + + // GL_NV_fence + bool fence; + + // GL_ANGLE_timer_query + bool timerQuery; + + // GL_EXT_robustness + bool robustness; + + // GL_EXT_blend_minmax + bool blendMinMax; + + // GL_ANGLE_framebuffer_blit + bool framebufferBlit; + + // GL_ANGLE_framebuffer_multisample + bool framebufferMultisample; + + // GL_ANGLE_instanced_arrays + bool instancedArrays; + + // GL_ANGLE_pack_reverse_row_order + bool packReverseRowOrder; + + // GL_OES_standard_derivatives + bool standardDerivatives; + + // GL_EXT_shader_texture_lod + bool shaderTextureLOD; + + // GL_EXT_frag_depth + bool fragDepth; + + // GL_ANGLE_texture_usage + bool textureUsage; + + // GL_ANGLE_translated_shader_source + bool translatedShaderSource; + + // ES3 Extension support + + // GL_EXT_color_buffer_float + bool colorBufferFloat; +}; + +struct Caps +{ + Caps(); + + // Table 6.28, implementation dependent values + GLuint64 maxElementIndex; + GLuint max3DTextureSize; + GLuint max2DTextureSize; + GLuint maxArrayTextureLayers; + GLfloat maxLODBias; + GLuint maxCubeMapTextureSize; + GLuint maxRenderbufferSize; + GLuint maxDrawBuffers; + GLuint maxColorAttachments; + GLuint maxViewportWidth; + GLuint maxViewportHeight; + GLfloat minAliasedPointSize; + GLfloat maxAliasedPointSize; + GLfloat minAliasedLineWidth; + GLfloat maxAliasedLineWidth; + +}; + +} + +#endif // LIBGLESV2_CAPS_H diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp index e651785aed..8201acda10 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" // -// Copyright (c) 2002-2013 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,19 +11,25 @@ #include "libGLESv2/Context.h" #include "libGLESv2/main.h" -#include "libGLESv2/utilities.h" +#include "common/utilities.h" +#include "libGLESv2/formatutils.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Fence.h" #include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Query.h" #include "libGLESv2/Texture.h" #include "libGLESv2/ResourceManager.h" -#include "libGLESv2/renderer/IndexDataManager.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" +#include "libGLESv2/validationES.h" +#include "libGLESv2/TransformFeedback.h" #include "libEGL/Surface.h" @@ -32,95 +38,17 @@ namespace gl { -static const char* makeStaticString(const std::string& str) -{ - static std::set strings; - std::set::iterator it = strings.find(str); - if (it != strings.end()) - return it->c_str(); - - return strings.insert(str).first->c_str(); -} -Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) : mRenderer(renderer) +Context::Context(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) + : mRenderer(renderer) { ASSERT(robustAccess == false); // Unimplemented - mFenceHandleAllocator.setBaseHandle(0); - - setClearColor(0.0f, 0.0f, 0.0f, 0.0f); - - mState.depthClearValue = 1.0f; - mState.stencilClearValue = 0; - - mState.rasterizer.cullFace = false; - mState.rasterizer.cullMode = GL_BACK; - mState.rasterizer.frontFace = GL_CCW; - mState.rasterizer.polygonOffsetFill = false; - mState.rasterizer.polygonOffsetFactor = 0.0f; - mState.rasterizer.polygonOffsetUnits = 0.0f; - mState.rasterizer.pointDrawMode = false; - mState.rasterizer.multiSample = false; - mState.scissorTest = false; - mState.scissor.x = 0; - mState.scissor.y = 0; - mState.scissor.width = 0; - mState.scissor.height = 0; - - mState.blend.blend = false; - mState.blend.sourceBlendRGB = GL_ONE; - mState.blend.sourceBlendAlpha = GL_ONE; - mState.blend.destBlendRGB = GL_ZERO; - mState.blend.destBlendAlpha = GL_ZERO; - mState.blend.blendEquationRGB = GL_FUNC_ADD; - mState.blend.blendEquationAlpha = GL_FUNC_ADD; - mState.blend.sampleAlphaToCoverage = false; - mState.blend.dither = true; - - mState.blendColor.red = 0; - mState.blendColor.green = 0; - mState.blendColor.blue = 0; - mState.blendColor.alpha = 0; - - mState.depthStencil.depthTest = false; - mState.depthStencil.depthFunc = GL_LESS; - mState.depthStencil.depthMask = true; - mState.depthStencil.stencilTest = false; - mState.depthStencil.stencilFunc = GL_ALWAYS; - mState.depthStencil.stencilMask = -1; - mState.depthStencil.stencilWritemask = -1; - mState.depthStencil.stencilBackFunc = GL_ALWAYS; - mState.depthStencil.stencilBackMask = - 1; - mState.depthStencil.stencilBackWritemask = -1; - mState.depthStencil.stencilFail = GL_KEEP; - mState.depthStencil.stencilPassDepthFail = GL_KEEP; - mState.depthStencil.stencilPassDepthPass = GL_KEEP; - mState.depthStencil.stencilBackFail = GL_KEEP; - mState.depthStencil.stencilBackPassDepthFail = GL_KEEP; - mState.depthStencil.stencilBackPassDepthPass = GL_KEEP; - - mState.stencilRef = 0; - mState.stencilBackRef = 0; - - mState.sampleCoverage = false; - mState.sampleCoverageValue = 1.0f; - mState.sampleCoverageInvert = false; - mState.generateMipmapHint = GL_DONT_CARE; - mState.fragmentShaderDerivativeHint = GL_DONT_CARE; - - mState.lineWidth = 1.0f; - - mState.viewport.x = 0; - mState.viewport.y = 0; - mState.viewport.width = 0; - mState.viewport.height = 0; - mState.zNear = 0.0f; - mState.zFar = 1.0f; - - mState.blend.colorMaskRed = true; - mState.blend.colorMaskGreen = true; - mState.blend.colorMaskBlue = true; - mState.blend.colorMaskAlpha = true; + initCaps(clientVersion); + + mClientVersion = clientVersion; + + mFenceNVHandleAllocator.setBaseHandle(0); if (shareContext != NULL) { @@ -138,10 +66,12 @@ Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool n // 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, 0)); - mTextureCubeMapZero.set(new TextureCubeMap(mRenderer, 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)); - mState.activeSampler = 0; + bindVertexArray(0); bindArrayBuffer(0); bindElementArrayBuffer(0); bindTextureCubeMap(0); @@ -150,15 +80,29 @@ Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool n bindDrawFramebuffer(0); bindRenderbuffer(0); - mState.currentProgram = 0; - mCurrentProgramBinary.set(NULL); + bindGenericUniformBuffer(0); + for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++) + { + bindIndexedUniformBuffer(0, i, 0, -1); + } + + bindGenericTransformFeedbackBuffer(0); + for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + { + bindIndexedTransformFeedbackBuffer(0, i, 0, -1); + } - mState.packAlignment = 4; - mState.unpackAlignment = 4; - mState.packReverseRowOrder = false; + bindCopyReadBuffer(0); + bindCopyWriteBuffer(0); + bindPixelPackBuffer(0); + bindPixelUnpackBuffer(0); - mExtensionString = NULL; - mRendererString = NULL; + // [OpenGL ES 3.0.2] section 2.14.1 pg 85: + // In the initial state, a default transform feedback object is bound and treated as + // a transform feedback object with a name of zero. That object is bound any time + // BindTransformFeedback is called with id of zero + mTransformFeedbackZero.set(new TransformFeedback(0)); + bindTransformFeedback(0); mInvalidEnum = false; mInvalidValue = false; @@ -172,36 +116,33 @@ Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool n mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT); mRobustAccess = robustAccess; - mSupportsBGRATextures = false; - mSupportsDXT1Textures = false; - mSupportsDXT3Textures = false; - mSupportsDXT5Textures = false; - mSupportsEventQueries = false; - mSupportsOcclusionQueries = false; mNumCompressedTextureFormats = 0; + + mState.setContext(this); } Context::~Context() { - if (mState.currentProgram != 0) + GLuint currentProgram = mState.getCurrentProgramId(); + if (currentProgram != 0) { - Program *programObject = mResourceManager->getProgram(mState.currentProgram); + Program *programObject = mResourceManager->getProgram(currentProgram); if (programObject) { programObject->release(); } - mState.currentProgram = 0; + currentProgram = 0; } - mCurrentProgramBinary.set(NULL); + mState.setCurrentProgram(0, NULL); while (!mFramebufferMap.empty()) { deleteFramebuffer(mFramebufferMap.begin()->first); } - while (!mFenceMap.empty()) + while (!mFenceNVMap.empty()) { - deleteFence(mFenceMap.begin()->first); + deleteFenceNV(mFenceNVMap.begin()->first); } while (!mQueryMap.empty()) @@ -209,35 +150,26 @@ Context::~Context() deleteQuery(mQueryMap.begin()->first); } - for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) - { - for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) - { - mState.samplerTexture[type][sampler].set(NULL); - } - } - - for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) + while (!mVertexArrayMap.empty()) { - mIncompleteTextures[type].set(NULL); + deleteVertexArray(mVertexArrayMap.begin()->first); } - for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++) + mTransformFeedbackZero.set(NULL); + while (!mTransformFeedbackMap.empty()) { - mState.vertexAttribute[i].mBoundBuffer.set(NULL); + deleteTransformFeedback(mTransformFeedbackMap.begin()->first); } - for (int i = 0; i < QUERY_TYPE_COUNT; i++) + for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) { - mState.activeQuery[i].set(NULL); + mIncompleteTextures[type].set(NULL); } - mState.arrayBuffer.set(NULL); - mState.elementArrayBuffer.set(NULL); - mState.renderbuffer.set(NULL); - mTexture2DZero.set(NULL); mTextureCubeMapZero.set(NULL); + mTexture3DZero.set(NULL); + mTexture2DArrayZero.set(NULL); mResourceManager->release(); } @@ -247,61 +179,27 @@ void Context::makeCurrent(egl::Surface *surface) if (!mHasBeenCurrent) { mMajorShaderModel = mRenderer->getMajorShaderModel(); - mMaximumPointSize = mRenderer->getMaxPointSize(); mSupportsVertexTexture = mRenderer->getVertexTextureSupport(); - mSupportsNonPower2Texture = mRenderer->getNonPower2TextureSupport(); - mSupportsInstancing = mRenderer->getInstancingSupport(); - - mMaxViewportDimension = mRenderer->getMaxViewportDimension(); - mMaxTextureDimension = std::min(std::min(mRenderer->getMaxTextureWidth(), mRenderer->getMaxTextureHeight()), - (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE); - mMaxCubeTextureDimension = std::min(mMaxTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE); - mMaxRenderbufferDimension = mMaxTextureDimension; - mMaxTextureLevel = log2(mMaxTextureDimension) + 1; - mMaxTextureAnisotropy = mRenderer->getTextureMaxAnisotropy(); - TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d, MaxTextureAnisotropy=%f", - mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel, mMaxTextureAnisotropy); - - mSupportsEventQueries = mRenderer->getEventQuerySupport(); - mSupportsOcclusionQueries = mRenderer->getOcclusionQuerySupport(); - mSupportsBGRATextures = mRenderer->getBGRATextureSupport(); - mSupportsDXT1Textures = mRenderer->getDXT1TextureSupport(); - mSupportsDXT3Textures = mRenderer->getDXT3TextureSupport(); - mSupportsDXT5Textures = mRenderer->getDXT5TextureSupport(); - mSupportsFloat32Textures = mRenderer->getFloat32TextureSupport(&mSupportsFloat32LinearFilter, &mSupportsFloat32RenderableTextures); - mSupportsFloat16Textures = mRenderer->getFloat16TextureSupport(&mSupportsFloat16LinearFilter, &mSupportsFloat16RenderableTextures); - mSupportsLuminanceTextures = mRenderer->getLuminanceTextureSupport(); - mSupportsLuminanceAlphaTextures = mRenderer->getLuminanceAlphaTextureSupport(); - mSupportsDepthTextures = mRenderer->getDepthTextureSupport(); - mSupportsTextureFilterAnisotropy = mRenderer->getTextureFilterAnisotropySupport(); - mSupports32bitIndices = mRenderer->get32BitIndexSupport(); mNumCompressedTextureFormats = 0; - if (supportsDXT1Textures()) + if (mExtensions.textureCompressionDXT1) { mNumCompressedTextureFormats += 2; } - if (supportsDXT3Textures()) + if (mExtensions.textureCompressionDXT3) { mNumCompressedTextureFormats += 1; } - if (supportsDXT5Textures()) + if (mExtensions.textureCompressionDXT5) { mNumCompressedTextureFormats += 1; } - initExtensionString(); initRendererString(); + initExtensionStrings(); - mState.viewport.x = 0; - mState.viewport.y = 0; - mState.viewport.width = surface->getWidth(); - mState.viewport.height = surface->getHeight(); - - mState.scissor.x = 0; - mState.scissor.y = 0; - mState.scissor.width = surface->getWidth(); - mState.scissor.height = surface->getHeight(); + mState.setViewportParams(0, 0, surface->getWidth(), surface->getHeight()); + mState.setScissorParams(0, 0, surface->getWidth(), surface->getHeight()); mHasBeenCurrent = true; } @@ -314,6 +212,9 @@ void Context::makeCurrent(egl::Surface *surface) Framebuffer *framebufferZero = new DefaultFramebuffer(mRenderer, colorbufferZero, depthStencilbufferZero); setFramebufferZero(framebufferZero); + + // Store the current client version in the renderer + mRenderer->setCurrentClientVersion(mClientVersion); } // NOTE: this function should not assume that this context is current! @@ -329,623 +230,461 @@ bool Context::isContextLost() return mContextLost; } -void Context::setClearColor(float red, float green, float blue, float alpha) +GLuint Context::createBuffer() { - mState.colorClearValue.red = red; - mState.colorClearValue.green = green; - mState.colorClearValue.blue = blue; - mState.colorClearValue.alpha = alpha; + return mResourceManager->createBuffer(); } -void Context::setClearDepth(float depth) +GLuint Context::createProgram() { - mState.depthClearValue = depth; + return mResourceManager->createProgram(); } -void Context::setClearStencil(int stencil) +GLuint Context::createShader(GLenum type) { - mState.stencilClearValue = stencil; + return mResourceManager->createShader(type); } -void Context::setCullFace(bool enabled) +GLuint Context::createTexture() { - mState.rasterizer.cullFace = enabled; + return mResourceManager->createTexture(); } -bool Context::isCullFaceEnabled() const +GLuint Context::createRenderbuffer() { - return mState.rasterizer.cullFace; + return mResourceManager->createRenderbuffer(); } -void Context::setCullMode(GLenum mode) +GLsync Context::createFenceSync(GLenum condition) { - mState.rasterizer.cullMode = mode; -} + GLuint handle = mResourceManager->createFenceSync(); -void Context::setFrontFace(GLenum front) -{ - mState.rasterizer.frontFace = front; -} + gl::FenceSync *fenceSync = mResourceManager->getFenceSync(handle); + ASSERT(fenceSync); -void Context::setDepthTest(bool enabled) -{ - mState.depthStencil.depthTest = enabled; -} + fenceSync->set(condition); -bool Context::isDepthTestEnabled() const -{ - return mState.depthStencil.depthTest; + return reinterpret_cast(handle); } -void Context::setDepthFunc(GLenum depthFunc) +GLuint Context::createVertexArray() { - mState.depthStencil.depthFunc = depthFunc; -} + GLuint handle = mVertexArrayHandleAllocator.allocate(); -void Context::setDepthRange(float zNear, float zFar) -{ - mState.zNear = zNear; - mState.zFar = zFar; + // Although the spec states VAO state is not initialized until the object is bound, + // we create it immediately. The resulting behaviour is transparent to the application, + // since it's not currently possible to access the state until the object is bound. + VertexArray *vertexArray = new VertexArray(mRenderer->createVertexArray(), handle, MAX_VERTEX_ATTRIBS); + mVertexArrayMap[handle] = vertexArray; + return handle; } -void Context::setBlend(bool enabled) +GLuint Context::createSampler() { - mState.blend.blend = enabled; + return mResourceManager->createSampler(); } -bool Context::isBlendEnabled() const +GLuint Context::createTransformFeedback() { - return mState.blend.blend; + GLuint handle = mTransformFeedbackAllocator.allocate(); + TransformFeedback *transformFeedback = new TransformFeedback(handle); + transformFeedback->addRef(); + mTransformFeedbackMap[handle] = transformFeedback; + return handle; } -void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha) +// Returns an unused framebuffer name +GLuint Context::createFramebuffer() { - mState.blend.sourceBlendRGB = sourceRGB; - mState.blend.destBlendRGB = destRGB; - mState.blend.sourceBlendAlpha = sourceAlpha; - mState.blend.destBlendAlpha = destAlpha; -} + GLuint handle = mFramebufferHandleAllocator.allocate(); -void Context::setBlendColor(float red, float green, float blue, float alpha) -{ - mState.blendColor.red = red; - mState.blendColor.green = green; - mState.blendColor.blue = blue; - mState.blendColor.alpha = alpha; -} + mFramebufferMap[handle] = NULL; -void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation) -{ - mState.blend.blendEquationRGB = rgbEquation; - mState.blend.blendEquationAlpha = alphaEquation; + return handle; } -void Context::setStencilTest(bool enabled) +GLuint Context::createFenceNV() { - mState.depthStencil.stencilTest = enabled; -} + GLuint handle = mFenceNVHandleAllocator.allocate(); -bool Context::isStencilTestEnabled() const -{ - return mState.depthStencil.stencilTest; -} + mFenceNVMap[handle] = new FenceNV(mRenderer); -void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask) -{ - mState.depthStencil.stencilFunc = stencilFunc; - mState.stencilRef = (stencilRef > 0) ? stencilRef : 0; - mState.depthStencil.stencilMask = stencilMask; + return handle; } -void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask) +// Returns an unused query name +GLuint Context::createQuery() { - mState.depthStencil.stencilBackFunc = stencilBackFunc; - mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0; - mState.depthStencil.stencilBackMask = stencilBackMask; -} + GLuint handle = mQueryHandleAllocator.allocate(); -void Context::setStencilWritemask(GLuint stencilWritemask) -{ - mState.depthStencil.stencilWritemask = stencilWritemask; -} + mQueryMap[handle] = NULL; -void Context::setStencilBackWritemask(GLuint stencilBackWritemask) -{ - mState.depthStencil.stencilBackWritemask = stencilBackWritemask; + return handle; } -void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass) +void Context::deleteBuffer(GLuint buffer) { - mState.depthStencil.stencilFail = stencilFail; - mState.depthStencil.stencilPassDepthFail = stencilPassDepthFail; - mState.depthStencil.stencilPassDepthPass = stencilPassDepthPass; -} + if (mResourceManager->getBuffer(buffer)) + { + detachBuffer(buffer); + } -void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass) -{ - mState.depthStencil.stencilBackFail = stencilBackFail; - mState.depthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail; - mState.depthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass; + mResourceManager->deleteBuffer(buffer); } -void Context::setPolygonOffsetFill(bool enabled) +void Context::deleteShader(GLuint shader) { - mState.rasterizer.polygonOffsetFill = enabled; + mResourceManager->deleteShader(shader); } -bool Context::isPolygonOffsetFillEnabled() const +void Context::deleteProgram(GLuint program) { - return mState.rasterizer.polygonOffsetFill; + mResourceManager->deleteProgram(program); } -void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units) +void Context::deleteTexture(GLuint texture) { - // An application can pass NaN values here, so handle this gracefully - mState.rasterizer.polygonOffsetFactor = factor != factor ? 0.0f : factor; - mState.rasterizer.polygonOffsetUnits = units != units ? 0.0f : units; -} + if (mResourceManager->getTexture(texture)) + { + detachTexture(texture); + } -void Context::setSampleAlphaToCoverage(bool enabled) -{ - mState.blend.sampleAlphaToCoverage = enabled; + mResourceManager->deleteTexture(texture); } -bool Context::isSampleAlphaToCoverageEnabled() const +void Context::deleteRenderbuffer(GLuint renderbuffer) { - return mState.blend.sampleAlphaToCoverage; -} + if (mResourceManager->getRenderbuffer(renderbuffer)) + { + detachRenderbuffer(renderbuffer); + } -void Context::setSampleCoverage(bool enabled) -{ - mState.sampleCoverage = enabled; + mResourceManager->deleteRenderbuffer(renderbuffer); } -bool Context::isSampleCoverageEnabled() const +void Context::deleteFenceSync(GLsync fenceSync) { - return mState.sampleCoverage; + // The spec specifies the underlying Fence object is not deleted until all current + // wait commands finish. However, since the name becomes invalid, we cannot query the fence, + // and since our API is currently designed for being called from a single thread, we can delete + // the fence immediately. + mResourceManager->deleteFenceSync(reinterpret_cast(fenceSync)); } -void Context::setSampleCoverageParams(GLclampf value, bool invert) +void Context::deleteVertexArray(GLuint vertexArray) { - mState.sampleCoverageValue = value; - mState.sampleCoverageInvert = invert; -} + auto vertexArrayObject = mVertexArrayMap.find(vertexArray); -void Context::setScissorTest(bool enabled) -{ - mState.scissorTest = enabled; -} + if (vertexArrayObject != mVertexArrayMap.end()) + { + detachVertexArray(vertexArray); -bool Context::isScissorTestEnabled() const -{ - return mState.scissorTest; + mVertexArrayHandleAllocator.release(vertexArrayObject->first); + delete vertexArrayObject->second; + mVertexArrayMap.erase(vertexArrayObject); + } } -void Context::setDither(bool enabled) +void Context::deleteSampler(GLuint sampler) { - mState.blend.dither = enabled; -} + if (mResourceManager->getSampler(sampler)) + { + detachSampler(sampler); + } -bool Context::isDitherEnabled() const -{ - return mState.blend.dither; + mResourceManager->deleteSampler(sampler); } -void Context::setLineWidth(GLfloat width) +void Context::deleteTransformFeedback(GLuint transformFeedback) { - mState.lineWidth = width; + TransformFeedbackMap::const_iterator iter = mTransformFeedbackMap.find(transformFeedback); + if (iter != mTransformFeedbackMap.end()) + { + detachTransformFeedback(transformFeedback); + mTransformFeedbackAllocator.release(transformFeedback); + iter->second->release(); + mTransformFeedbackMap.erase(iter); + } } -void Context::setGenerateMipmapHint(GLenum hint) +void Context::deleteFramebuffer(GLuint framebuffer) { - mState.generateMipmapHint = hint; -} + FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer); -void Context::setFragmentShaderDerivativeHint(GLenum hint) -{ - mState.fragmentShaderDerivativeHint = hint; - // TODO: Propagate the hint to shader translator so we can write - // ddx, ddx_coarse, or ddx_fine depending on the hint. - // Ignore for now. It is valid for implementations to ignore hint. -} + if (framebufferObject != mFramebufferMap.end()) + { + detachFramebuffer(framebuffer); -void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) -{ - mState.viewport.x = x; - mState.viewport.y = y; - mState.viewport.width = width; - mState.viewport.height = height; + mFramebufferHandleAllocator.release(framebufferObject->first); + delete framebufferObject->second; + mFramebufferMap.erase(framebufferObject); + } } -void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height) +void Context::deleteFenceNV(GLuint fence) { - mState.scissor.x = x; - mState.scissor.y = y; - mState.scissor.width = width; - mState.scissor.height = height; + FenceNVMap::iterator fenceObject = mFenceNVMap.find(fence); + + if (fenceObject != mFenceNVMap.end()) + { + mFenceNVHandleAllocator.release(fenceObject->first); + delete fenceObject->second; + mFenceNVMap.erase(fenceObject); + } } -void Context::setColorMask(bool red, bool green, bool blue, bool alpha) +void Context::deleteQuery(GLuint query) { - mState.blend.colorMaskRed = red; - mState.blend.colorMaskGreen = green; - mState.blend.colorMaskBlue = blue; - mState.blend.colorMaskAlpha = alpha; + QueryMap::iterator queryObject = mQueryMap.find(query); + if (queryObject != mQueryMap.end()) + { + mQueryHandleAllocator.release(queryObject->first); + if (queryObject->second) + { + queryObject->second->release(); + } + mQueryMap.erase(queryObject); + } } -void Context::setDepthMask(bool mask) +Buffer *Context::getBuffer(GLuint handle) { - mState.depthStencil.depthMask = mask; + return mResourceManager->getBuffer(handle); } -void Context::setActiveSampler(unsigned int active) +Shader *Context::getShader(GLuint handle) const { - mState.activeSampler = active; + return mResourceManager->getShader(handle); } -GLuint Context::getReadFramebufferHandle() const +Program *Context::getProgram(GLuint handle) const { - return mState.readFramebuffer; + return mResourceManager->getProgram(handle); } -GLuint Context::getDrawFramebufferHandle() const +Texture *Context::getTexture(GLuint handle) const { - return mState.drawFramebuffer; + return mResourceManager->getTexture(handle); } -GLuint Context::getRenderbufferHandle() const +Renderbuffer *Context::getRenderbuffer(GLuint handle) { - return mState.renderbuffer.id(); + return mResourceManager->getRenderbuffer(handle); } -GLuint Context::getArrayBufferHandle() const +FenceSync *Context::getFenceSync(GLsync handle) const { - return mState.arrayBuffer.id(); + return mResourceManager->getFenceSync(reinterpret_cast(handle)); } -GLuint Context::getActiveQuery(GLenum target) const +VertexArray *Context::getVertexArray(GLuint handle) const { - Query *queryObject = NULL; - - switch (target) - { - case GL_ANY_SAMPLES_PASSED_EXT: - queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED].get(); - break; - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: - queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE].get(); - break; - default: - ASSERT(false); - } + auto vertexArray = mVertexArrayMap.find(handle); - if (queryObject) + if (vertexArray == mVertexArrayMap.end()) { - return queryObject->id(); + return NULL; } else { - return 0; + return vertexArray->second; } } -void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) +Sampler *Context::getSampler(GLuint handle) const { - mState.vertexAttribute[attribNum].mArrayEnabled = enabled; + return mResourceManager->getSampler(handle); } -const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum) +TransformFeedback *Context::getTransformFeedback(GLuint handle) const { - return mState.vertexAttribute[attribNum]; + if (handle == 0) + { + return mTransformFeedbackZero.get(); + } + else + { + TransformFeedbackMap::const_iterator iter = mTransformFeedbackMap.find(handle); + return (iter != mTransformFeedbackMap.end()) ? iter->second : NULL; + } } -void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized, - GLsizei stride, const void *pointer) +bool Context::isSampler(GLuint samplerName) const { - mState.vertexAttribute[attribNum].mBoundBuffer.set(boundBuffer); - mState.vertexAttribute[attribNum].mSize = size; - mState.vertexAttribute[attribNum].mType = type; - mState.vertexAttribute[attribNum].mNormalized = normalized; - mState.vertexAttribute[attribNum].mStride = stride; - mState.vertexAttribute[attribNum].mPointer = pointer; + return mResourceManager->isSampler(samplerName); } -const void *Context::getVertexAttribPointer(unsigned int attribNum) const +void Context::bindArrayBuffer(unsigned int buffer) { - return mState.vertexAttribute[attribNum].mPointer; -} + mResourceManager->checkBufferAllocation(buffer); -void Context::setPackAlignment(GLint alignment) -{ - mState.packAlignment = alignment; + mState.setArrayBufferBinding(getBuffer(buffer)); } -GLint Context::getPackAlignment() const +void Context::bindElementArrayBuffer(unsigned int buffer) { - return mState.packAlignment; + mResourceManager->checkBufferAllocation(buffer); + + mState.getVertexArray()->setElementArrayBuffer(getBuffer(buffer)); } -void Context::setUnpackAlignment(GLint alignment) +void Context::bindTexture2D(GLuint texture) { - mState.unpackAlignment = alignment; + mResourceManager->checkTextureAllocation(texture, TEXTURE_2D); + + mState.setSamplerTexture(TEXTURE_2D, getTexture(texture)); } -GLint Context::getUnpackAlignment() const +void Context::bindTextureCubeMap(GLuint texture) { - return mState.unpackAlignment; + mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE); + + mState.setSamplerTexture(TEXTURE_CUBE, getTexture(texture)); } -void Context::setPackReverseRowOrder(bool reverseRowOrder) +void Context::bindTexture3D(GLuint texture) { - mState.packReverseRowOrder = reverseRowOrder; + mResourceManager->checkTextureAllocation(texture, TEXTURE_3D); + + mState.setSamplerTexture(TEXTURE_3D, getTexture(texture)); } -bool Context::getPackReverseRowOrder() const +void Context::bindTexture2DArray(GLuint texture) { - return mState.packReverseRowOrder; + mResourceManager->checkTextureAllocation(texture, TEXTURE_2D_ARRAY); + + mState.setSamplerTexture(TEXTURE_2D_ARRAY, getTexture(texture)); } -GLuint Context::createBuffer() +void Context::bindReadFramebuffer(GLuint framebuffer) { - return mResourceManager->createBuffer(); + if (!getFramebuffer(framebuffer)) + { + mFramebufferMap[framebuffer] = new Framebuffer(mRenderer, framebuffer); + } + + mState.setReadFramebufferBinding(getFramebuffer(framebuffer)); } -GLuint Context::createProgram() +void Context::bindDrawFramebuffer(GLuint framebuffer) { - return mResourceManager->createProgram(); + if (!getFramebuffer(framebuffer)) + { + mFramebufferMap[framebuffer] = new Framebuffer(mRenderer, framebuffer); + } + + mState.setDrawFramebufferBinding(getFramebuffer(framebuffer)); } -GLuint Context::createShader(GLenum type) +void Context::bindRenderbuffer(GLuint renderbuffer) { - return mResourceManager->createShader(type); + mResourceManager->checkRenderbufferAllocation(renderbuffer); + + mState.setRenderbufferBinding(getRenderbuffer(renderbuffer)); } -GLuint Context::createTexture() +void Context::bindVertexArray(GLuint vertexArray) { - return mResourceManager->createTexture(); + if (!getVertexArray(vertexArray)) + { + VertexArray *vertexArrayObject = new VertexArray(mRenderer->createVertexArray(), vertexArray, MAX_VERTEX_ATTRIBS); + mVertexArrayMap[vertexArray] = vertexArrayObject; + } + + mState.setVertexArrayBinding(getVertexArray(vertexArray)); } -GLuint Context::createRenderbuffer() +void Context::bindSampler(GLuint textureUnit, GLuint sampler) { - return mResourceManager->createRenderbuffer(); + ASSERT(textureUnit < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS); // TODO: Update for backend-determined array size + mResourceManager->checkSamplerAllocation(sampler); + + mState.setSamplerBinding(textureUnit, getSampler(sampler)); } -// Returns an unused framebuffer name -GLuint Context::createFramebuffer() +void Context::bindGenericUniformBuffer(GLuint buffer) { - GLuint handle = mFramebufferHandleAllocator.allocate(); - - mFramebufferMap[handle] = NULL; + mResourceManager->checkBufferAllocation(buffer); - return handle; + mState.setGenericUniformBufferBinding(getBuffer(buffer)); } -GLuint Context::createFence() +void Context::bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size) { - GLuint handle = mFenceHandleAllocator.allocate(); - - mFenceMap[handle] = new Fence(mRenderer); + mResourceManager->checkBufferAllocation(buffer); - return handle; + mState.setIndexedUniformBufferBinding(index, getBuffer(buffer), offset, size); } -// Returns an unused query name -GLuint Context::createQuery() +void Context::bindGenericTransformFeedbackBuffer(GLuint buffer) { - GLuint handle = mQueryHandleAllocator.allocate(); - - mQueryMap[handle] = NULL; + mResourceManager->checkBufferAllocation(buffer); - return handle; + mState.setGenericTransformFeedbackBufferBinding(getBuffer(buffer)); } -void Context::deleteBuffer(GLuint buffer) +void Context::bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size) { - if (mResourceManager->getBuffer(buffer)) - { - detachBuffer(buffer); - } - - mResourceManager->deleteBuffer(buffer); + mResourceManager->checkBufferAllocation(buffer); + + mState.setIndexedTransformFeedbackBufferBinding(index, getBuffer(buffer), offset, size); } -void Context::deleteShader(GLuint shader) +void Context::bindCopyReadBuffer(GLuint buffer) { - mResourceManager->deleteShader(shader); + mResourceManager->checkBufferAllocation(buffer); + + mState.setCopyReadBufferBinding(getBuffer(buffer)); } -void Context::deleteProgram(GLuint program) +void Context::bindCopyWriteBuffer(GLuint buffer) { - mResourceManager->deleteProgram(program); + mResourceManager->checkBufferAllocation(buffer); + + mState.setCopyWriteBufferBinding(getBuffer(buffer)); } -void Context::deleteTexture(GLuint texture) +void Context::bindPixelPackBuffer(GLuint buffer) { - if (mResourceManager->getTexture(texture)) - { - detachTexture(texture); - } + mResourceManager->checkBufferAllocation(buffer); - mResourceManager->deleteTexture(texture); + mState.setPixelPackBufferBinding(getBuffer(buffer)); } -void Context::deleteRenderbuffer(GLuint renderbuffer) +void Context::bindPixelUnpackBuffer(GLuint buffer) { - if (mResourceManager->getRenderbuffer(renderbuffer)) - { - detachRenderbuffer(renderbuffer); - } - - mResourceManager->deleteRenderbuffer(renderbuffer); + mResourceManager->checkBufferAllocation(buffer); + + mState.setPixelUnpackBufferBinding(getBuffer(buffer)); } -void Context::deleteFramebuffer(GLuint framebuffer) +void Context::useProgram(GLuint program) { - FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer); + GLuint priorProgramId = mState.getCurrentProgramId(); + Program *priorProgram = mResourceManager->getProgram(priorProgramId); - if (framebufferObject != mFramebufferMap.end()) + if (priorProgramId != program) { - detachFramebuffer(framebuffer); + mState.setCurrentProgram(program, mResourceManager->getProgram(program)); - mFramebufferHandleAllocator.release(framebufferObject->first); - delete framebufferObject->second; - mFramebufferMap.erase(framebufferObject); + if (priorProgram) + { + priorProgram->release(); + } } } -void Context::deleteFence(GLuint fence) +void Context::linkProgram(GLuint program) { - FenceMap::iterator fenceObject = mFenceMap.find(fence); - - if (fenceObject != mFenceMap.end()) - { - mFenceHandleAllocator.release(fenceObject->first); - delete fenceObject->second; - mFenceMap.erase(fenceObject); - } -} - -void Context::deleteQuery(GLuint query) -{ - QueryMap::iterator queryObject = mQueryMap.find(query); - if (queryObject != mQueryMap.end()) - { - mQueryHandleAllocator.release(queryObject->first); - if (queryObject->second) - { - queryObject->second->release(); - } - mQueryMap.erase(queryObject); - } -} - -Buffer *Context::getBuffer(GLuint handle) -{ - return mResourceManager->getBuffer(handle); -} - -Shader *Context::getShader(GLuint handle) -{ - return mResourceManager->getShader(handle); -} - -Program *Context::getProgram(GLuint handle) -{ - return mResourceManager->getProgram(handle); -} - -Texture *Context::getTexture(GLuint handle) -{ - return mResourceManager->getTexture(handle); -} - -Renderbuffer *Context::getRenderbuffer(GLuint handle) -{ - return mResourceManager->getRenderbuffer(handle); -} - -Framebuffer *Context::getReadFramebuffer() -{ - return getFramebuffer(mState.readFramebuffer); -} - -Framebuffer *Context::getDrawFramebuffer() -{ - return mBoundDrawFramebuffer; -} - -void Context::bindArrayBuffer(unsigned int buffer) -{ - mResourceManager->checkBufferAllocation(buffer); - - mState.arrayBuffer.set(getBuffer(buffer)); -} - -void Context::bindElementArrayBuffer(unsigned int buffer) -{ - mResourceManager->checkBufferAllocation(buffer); - - mState.elementArrayBuffer.set(getBuffer(buffer)); -} - -void Context::bindTexture2D(GLuint texture) -{ - mResourceManager->checkTextureAllocation(texture, TEXTURE_2D); - - mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture)); -} - -void Context::bindTextureCubeMap(GLuint texture) -{ - mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE); - - mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture)); -} - -void Context::bindReadFramebuffer(GLuint framebuffer) -{ - if (!getFramebuffer(framebuffer)) - { - mFramebufferMap[framebuffer] = new Framebuffer(mRenderer); - } - - mState.readFramebuffer = framebuffer; -} - -void Context::bindDrawFramebuffer(GLuint framebuffer) -{ - if (!getFramebuffer(framebuffer)) - { - mFramebufferMap[framebuffer] = new Framebuffer(mRenderer); - } - - mState.drawFramebuffer = framebuffer; - - mBoundDrawFramebuffer = getFramebuffer(framebuffer); -} - -void Context::bindRenderbuffer(GLuint renderbuffer) -{ - mResourceManager->checkRenderbufferAllocation(renderbuffer); - - mState.renderbuffer.set(getRenderbuffer(renderbuffer)); -} - -void Context::useProgram(GLuint program) -{ - GLuint priorProgram = mState.currentProgram; - mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged. - - if (priorProgram != program) - { - Program *newProgram = mResourceManager->getProgram(program); - Program *oldProgram = mResourceManager->getProgram(priorProgram); - mCurrentProgramBinary.set(NULL); - - if (newProgram) - { - newProgram->addRef(); - mCurrentProgramBinary.set(newProgram->getProgramBinary()); - } - - if (oldProgram) - { - oldProgram->release(); - } - } -} - -void Context::linkProgram(GLuint program) -{ - Program *programObject = mResourceManager->getProgram(program); + Program *programObject = mResourceManager->getProgram(program); bool linked = programObject->link(); // if the current program was relinked successfully we // need to install the new executables - if (linked && program == mState.currentProgram) + if (linked && program == mState.getCurrentProgramId()) { - mCurrentProgramBinary.set(programObject->getProgramBinary()); + mState.setCurrentProgramBinary(programObject->getProgramBinary()); } } @@ -957,68 +696,25 @@ void Context::setProgramBinary(GLuint program, const void *binary, GLint length) // if the current program was reloaded successfully we // need to install the new executables - if (loaded && program == mState.currentProgram) + if (loaded && program == mState.getCurrentProgramId()) { - mCurrentProgramBinary.set(programObject->getProgramBinary()); + mState.setCurrentProgramBinary(programObject->getProgramBinary()); } } -void Context::beginQuery(GLenum target, GLuint query) +void Context::bindTransformFeedback(GLuint transformFeedback) { - // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an - // of zero, if the active query object name for is non-zero (for the - // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if - // the active query for either target is non-zero), if is the name of an - // existing query object whose type does not match , or if is the - // active query object name for any query type, the error INVALID_OPERATION is - // generated. - - // Ensure no other queries are active - // NOTE: If other queries than occlusion are supported, we will need to check - // separately that: - // a) The query ID passed is not the current active query for any target/type - // b) There are no active queries for the requested target (and in the case - // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, - // no query may be active for either if glBeginQuery targets either. - for (int i = 0; i < QUERY_TYPE_COUNT; i++) - { - if (mState.activeQuery[i].get() != NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - } - - QueryType qType; - switch (target) - { - case GL_ANY_SAMPLES_PASSED_EXT: - qType = QUERY_ANY_SAMPLES_PASSED; - break; - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: - qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE; - break; - default: - ASSERT(false); - return; - } + mState.setTransformFeedbackBinding(getTransformFeedback(transformFeedback)); +} +void Context::beginQuery(GLenum target, GLuint query) +{ Query *queryObject = getQuery(query, true, target); - - // check that name was obtained with glGenQueries - if (!queryObject) - { - return gl::error(GL_INVALID_OPERATION); - } - - // check for type mismatch - if (queryObject->getType() != target) - { - return gl::error(GL_INVALID_OPERATION); - } + ASSERT(queryObject); // set query as active for specified target - mState.activeQuery[qType].set(queryObject); + mState.setActiveQuery(target, queryObject); // begin query queryObject->begin(); @@ -1026,76 +722,62 @@ void Context::beginQuery(GLenum target, GLuint query) void Context::endQuery(GLenum target) { - QueryType qType; - - switch (target) - { - case GL_ANY_SAMPLES_PASSED_EXT: - qType = QUERY_ANY_SAMPLES_PASSED; - break; - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: - qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE; - break; - default: - ASSERT(false); - return; - } - - Query *queryObject = mState.activeQuery[qType].get(); - - if (queryObject == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } + Query *queryObject = mState.getActiveQuery(target); + ASSERT(queryObject); queryObject->end(); - mState.activeQuery[qType].set(NULL); + mState.setActiveQuery(target, NULL); } void Context::setFramebufferZero(Framebuffer *buffer) { - delete mFramebufferMap[0]; - mFramebufferMap[0] = buffer; - if (mState.drawFramebuffer == 0) + // First, check to see if the old default framebuffer + // was set for draw or read framebuffer, and change + // the bindings to point to the new one before deleting it. + if (mState.getDrawFramebuffer()->id() == 0) + { + mState.setDrawFramebufferBinding(buffer); + } + + if (mState.getReadFramebuffer()->id() == 0) { - mBoundDrawFramebuffer = buffer; + mState.setReadFramebufferBinding(buffer); } + + delete mFramebufferMap[0]; + mFramebufferMap[0] = buffer; } void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) { + ASSERT(getTextureCaps().get(internalformat).renderable); + RenderbufferStorage *renderbuffer = NULL; - switch (internalformat) + + if (GetDepthBits(internalformat) > 0 && GetStencilBits(internalformat) > 0) + { + renderbuffer = new gl::DepthStencilbuffer(mRenderer, width, height, samples); + } + else if (GetDepthBits(internalformat) > 0) { - case GL_DEPTH_COMPONENT16: renderbuffer = new gl::Depthbuffer(mRenderer, width, height, samples); - break; - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGB565: - case GL_RGB8_OES: - case GL_RGBA8_OES: - case GL_BGRA8_EXT: - renderbuffer = new gl::Colorbuffer(mRenderer,width, height, internalformat, samples); - break; - case GL_STENCIL_INDEX8: + } + else if (GetStencilBits(internalformat) > 0) + { renderbuffer = new gl::Stencilbuffer(mRenderer, width, height, samples); - break; - case GL_DEPTH24_STENCIL8_OES: - renderbuffer = new gl::DepthStencilbuffer(mRenderer, width, height, samples); - break; - default: - UNREACHABLE(); return; + } + else + { + renderbuffer = new gl::Colorbuffer(mRenderer, width, height, internalformat, samples); } - Renderbuffer *renderbufferObject = mState.renderbuffer.get(); - renderbufferObject->setStorage(renderbuffer); + mState.getCurrentRenderbuffer()->setStorage(renderbuffer); } -Framebuffer *Context::getFramebuffer(unsigned int handle) +Framebuffer *Context::getFramebuffer(unsigned int handle) const { - FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle); + FramebufferMap::const_iterator framebuffer = mFramebufferMap.find(handle); if (framebuffer == mFramebufferMap.end()) { @@ -1107,11 +789,11 @@ Framebuffer *Context::getFramebuffer(unsigned int handle) } } -Fence *Context::getFence(unsigned int handle) +FenceNV *Context::getFenceNV(unsigned int handle) { - FenceMap::iterator fence = mFenceMap.find(handle); + FenceNVMap::iterator fence = mFenceNVMap.find(handle); - if (fence == mFenceMap.end()) + if (fence == mFenceNVMap.end()) { return NULL; } @@ -1140,390 +822,248 @@ Query *Context::getQuery(unsigned int handle, bool create, GLenum type) } } -Buffer *Context::getArrayBuffer() +Texture *Context::getTargetTexture(GLenum target) const { - return mState.arrayBuffer.get(); + if (!ValidTextureTarget(this, target)) + { + return NULL; + } + + switch (target) + { + case GL_TEXTURE_2D: return getTexture2D(); + case GL_TEXTURE_CUBE_MAP: return getTextureCubeMap(); + case GL_TEXTURE_3D: return getTexture3D(); + case GL_TEXTURE_2D_ARRAY: return getTexture2DArray(); + default: return NULL; + } } -Buffer *Context::getElementArrayBuffer() +Texture2D *Context::getTexture2D() const { - return mState.elementArrayBuffer.get(); + return static_cast(getSamplerTexture(mState.getActiveSampler(), TEXTURE_2D)); } -ProgramBinary *Context::getCurrentProgramBinary() +TextureCubeMap *Context::getTextureCubeMap() const { - return mCurrentProgramBinary.get(); + return static_cast(getSamplerTexture(mState.getActiveSampler(), TEXTURE_CUBE)); } -Texture2D *Context::getTexture2D() +Texture3D *Context::getTexture3D() const { - return static_cast(getSamplerTexture(mState.activeSampler, TEXTURE_2D)); + return static_cast(getSamplerTexture(mState.getActiveSampler(), TEXTURE_3D)); } -TextureCubeMap *Context::getTextureCubeMap() +Texture2DArray *Context::getTexture2DArray() const { - return static_cast(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE)); + return static_cast(getSamplerTexture(mState.getActiveSampler(), TEXTURE_2D_ARRAY)); } -Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type) +Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type) const { - GLuint texid = mState.samplerTexture[type][sampler].id(); - - if (texid == 0) // Special case: 0 refers to different initial textures based on the target + if (mState.getSamplerTextureId(sampler, type) == 0) { switch (type) { default: UNREACHABLE(); - case TEXTURE_2D: return mTexture2DZero.get(); - case TEXTURE_CUBE: return mTextureCubeMapZero.get(); + 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 mState.samplerTexture[type][sampler].get(); + else + { + return mState.getSamplerTexture(sampler, type); + } } -bool Context::getBooleanv(GLenum pname, GLboolean *params) +void Context::getBooleanv(GLenum pname, GLboolean *params) { switch (pname) { case GL_SHADER_COMPILER: *params = GL_TRUE; break; - case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break; - case GL_DEPTH_WRITEMASK: *params = mState.depthStencil.depthMask; break; - case GL_COLOR_WRITEMASK: - params[0] = mState.blend.colorMaskRed; - params[1] = mState.blend.colorMaskGreen; - params[2] = mState.blend.colorMaskBlue; - params[3] = mState.blend.colorMaskAlpha; - break; - case GL_CULL_FACE: *params = mState.rasterizer.cullFace; break; - case GL_POLYGON_OFFSET_FILL: *params = mState.rasterizer.polygonOffsetFill; break; - case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.blend.sampleAlphaToCoverage; break; - case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break; - case GL_SCISSOR_TEST: *params = mState.scissorTest; break; - case GL_STENCIL_TEST: *params = mState.depthStencil.stencilTest; break; - case GL_DEPTH_TEST: *params = mState.depthStencil.depthTest; break; - case GL_BLEND: *params = mState.blend.blend; break; - case GL_DITHER: *params = mState.blend.dither; break; case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break; default: - return false; + mState.getBooleanv(pname, params); + break; } - - return true; } -bool Context::getFloatv(GLenum pname, GLfloat *params) +void Context::getFloatv(GLenum pname, GLfloat *params) { - // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation - // because it is stored as a float, despite the fact that the GL ES 2.0 spec names - // GetIntegerv as its native query function. As it would require conversion in any - // case, this should make no difference to the calling application. + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. switch (pname) { - case GL_LINE_WIDTH: *params = mState.lineWidth; break; - case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break; - case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break; - case GL_POLYGON_OFFSET_FACTOR: *params = mState.rasterizer.polygonOffsetFactor; break; - case GL_POLYGON_OFFSET_UNITS: *params = mState.rasterizer.polygonOffsetUnits; break; case GL_ALIASED_LINE_WIDTH_RANGE: - params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN; - params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX; + params[0] = mCaps.minAliasedLineWidth; + params[1] = mCaps.maxAliasedLineWidth; break; case GL_ALIASED_POINT_SIZE_RANGE: - params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN; - params[1] = getMaximumPointSize(); - break; - case GL_DEPTH_RANGE: - params[0] = mState.zNear; - params[1] = mState.zFar; - break; - case GL_COLOR_CLEAR_VALUE: - params[0] = mState.colorClearValue.red; - params[1] = mState.colorClearValue.green; - params[2] = mState.colorClearValue.blue; - params[3] = mState.colorClearValue.alpha; - break; - case GL_BLEND_COLOR: - params[0] = mState.blendColor.red; - params[1] = mState.blendColor.green; - params[2] = mState.blendColor.blue; - params[3] = mState.blendColor.alpha; + params[0] = mCaps.minAliasedPointSize; + params[1] = mCaps.maxAliasedPointSize; break; case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: - if (!supportsTextureFilterAnisotropy()) - { - return false; - } - *params = mMaxTextureAnisotropy; + ASSERT(mExtensions.textureFilterAnisotropic); + *params = mExtensions.maxTextureAnisotropy; break; default: - return false; + mState.getFloatv(pname, params); + break; } - - return true; } -bool Context::getIntegerv(GLenum pname, GLint *params) +void Context::getIntegerv(GLenum pname, GLint *params) { - if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT) - { - unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT); - - if (colorAttachment >= mRenderer->getMaxRenderTargets()) - { - // return true to stop further operation in the parent call - return gl::error(GL_INVALID_OPERATION, true); - } - - Framebuffer *framebuffer = getDrawFramebuffer(); - - *params = framebuffer->getDrawBufferState(colorAttachment); - return true; - } + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. - // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation - // because it is stored as a float, despite the fact that the GL ES 2.0 spec names - // GetIntegerv as its native query function. As it would require conversion in any - // case, this should make no difference to the calling application. You may find it in - // Context::getFloatv. 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_VARYING_VECTORS: *params = mRenderer->getMaxVaryingVectors(); break; - case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = mRenderer->getMaxCombinedTextureImageUnits(); break; - case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = mRenderer->getMaxVertexTextureImageUnits(); break; - case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break; - case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = mRenderer->getMaxFragmentUniformVectors(); break; - case GL_MAX_RENDERBUFFER_SIZE: *params = getMaximumRenderbufferDimension(); break; - case GL_MAX_COLOR_ATTACHMENTS_EXT: *params = mRenderer->getMaxRenderTargets(); break; - case GL_MAX_DRAW_BUFFERS_EXT: *params = mRenderer->getMaxRenderTargets(); break; - case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break; - case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break; - case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break; - case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer.id(); break; - //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE - case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mState.drawFramebuffer; break; - case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mState.readFramebuffer; break; - case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.id(); break; - case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break; - case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break; - case GL_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mState.packReverseRowOrder; break; - case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break; - case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break; - case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break; - case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break; - case GL_STENCIL_FUNC: *params = mState.depthStencil.stencilFunc; break; - case GL_STENCIL_REF: *params = mState.stencilRef; break; - case GL_STENCIL_VALUE_MASK: *params = mState.depthStencil.stencilMask; break; - case GL_STENCIL_BACK_FUNC: *params = mState.depthStencil.stencilBackFunc; break; - case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break; - case GL_STENCIL_BACK_VALUE_MASK: *params = mState.depthStencil.stencilBackMask; break; - case GL_STENCIL_FAIL: *params = mState.depthStencil.stencilFail; break; - case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.depthStencil.stencilPassDepthFail; break; - case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.depthStencil.stencilPassDepthPass; break; - case GL_STENCIL_BACK_FAIL: *params = mState.depthStencil.stencilBackFail; break; - case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.depthStencil.stencilBackPassDepthFail; break; - case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.depthStencil.stencilBackPassDepthPass; break; - case GL_DEPTH_FUNC: *params = mState.depthStencil.depthFunc; break; - case GL_BLEND_SRC_RGB: *params = mState.blend.sourceBlendRGB; break; - case GL_BLEND_SRC_ALPHA: *params = mState.blend.sourceBlendAlpha; break; - case GL_BLEND_DST_RGB: *params = mState.blend.destBlendRGB; break; - case GL_BLEND_DST_ALPHA: *params = mState.blend.destBlendAlpha; break; - case GL_BLEND_EQUATION_RGB: *params = mState.blend.blendEquationRGB; break; - case GL_BLEND_EQUATION_ALPHA: *params = mState.blend.blendEquationAlpha; break; - case GL_STENCIL_WRITEMASK: *params = mState.depthStencil.stencilWritemask; break; - case GL_STENCIL_BACK_WRITEMASK: *params = mState.depthStencil.stencilBackWritemask; break; - case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break; - case GL_SUBPIXEL_BITS: *params = 4; break; - case GL_MAX_TEXTURE_SIZE: *params = getMaximumTextureDimension(); break; - case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = getMaximumCubeTextureDimension(); break; - case GL_NUM_COMPRESSED_TEXTURE_FORMATS: + 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_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_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: - { - GLsizei maxSamples = getMaxSupportedSamples(); - if (maxSamples != 0) - { - *params = maxSamples; - } - else - { - return false; - } - - break; - } - case GL_SAMPLE_BUFFERS: - case GL_SAMPLES: - { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) - { - switch (pname) - { - case GL_SAMPLE_BUFFERS: - if (framebuffer->getSamples() != 0) - { - *params = 1; - } - else - { - *params = 0; - } - break; - case GL_SAMPLES: - *params = framebuffer->getSamples(); - break; - } - } - else - { - *params = 0; - } - } + *params = static_cast(getMaxSupportedSamples()); break; case GL_IMPLEMENTATION_COLOR_READ_TYPE: case GL_IMPLEMENTATION_COLOR_READ_FORMAT: { - GLenum format, type; - if (getCurrentReadFormatType(&format, &type)) - { - if (pname == GL_IMPLEMENTATION_COLOR_READ_FORMAT) - *params = format; - else - *params = type; - } + GLenum internalFormat, format, type; + getCurrentReadFormatType(&internalFormat, &format, &type); + if (pname == GL_IMPLEMENTATION_COLOR_READ_FORMAT) + *params = format; + else + *params = type; } break; case GL_MAX_VIEWPORT_DIMS: { - params[0] = mMaxViewportDimension; - params[1] = mMaxViewportDimension; + params[0] = mCaps.maxViewportWidth; + params[1] = mCaps.maxViewportHeight; } break; case GL_COMPRESSED_TEXTURE_FORMATS: { - if (supportsDXT1Textures()) + if (mExtensions.textureCompressionDXT1) { *params++ = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; *params++ = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; } - if (supportsDXT3Textures()) + if (mExtensions.textureCompressionDXT3) { *params++ = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE; } - if (supportsDXT5Textures()) + if (mExtensions.textureCompressionDXT5) { *params++ = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE; } } break; - case GL_VIEWPORT: - params[0] = mState.viewport.x; - params[1] = mState.viewport.y; - params[2] = mState.viewport.width; - params[3] = mState.viewport.height; + case GL_RESET_NOTIFICATION_STRATEGY_EXT: + *params = mResetStrategy; break; - case GL_SCISSOR_BOX: - params[0] = mState.scissor.x; - params[1] = mState.scissor.y; - params[2] = mState.scissor.width; - params[3] = mState.scissor.height; + case GL_NUM_PROGRAM_BINARY_FORMATS_OES: + *params = 1; break; - case GL_CULL_FACE_MODE: *params = mState.rasterizer.cullMode; break; - case GL_FRONT_FACE: *params = mState.rasterizer.frontFace; break; - case GL_RED_BITS: - case GL_GREEN_BITS: - case GL_BLUE_BITS: - case GL_ALPHA_BITS: - { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - gl::Renderbuffer *colorbuffer = framebuffer->getFirstColorbuffer(); - - if (colorbuffer) - { - switch (pname) - { - case GL_RED_BITS: *params = colorbuffer->getRedSize(); break; - case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break; - case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break; - case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break; - } - } - else - { - *params = 0; - } - } + case GL_PROGRAM_BINARY_FORMATS_OES: + *params = GL_PROGRAM_BINARY_ANGLE; break; - case GL_DEPTH_BITS: - { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - gl::Renderbuffer *depthbuffer = framebuffer->getDepthbuffer(); - - if (depthbuffer) - { - *params = depthbuffer->getDepthSize(); - } - else - { - *params = 0; - } - } + case GL_NUM_EXTENSIONS: + *params = static_cast(mExtensionStrings.size()); break; - case GL_STENCIL_BITS: - { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - gl::Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer(); + default: + mState.getIntegerv(pname, params); + break; + } +} - if (stencilbuffer) - { - *params = stencilbuffer->getStencilSize(); - } - else - { - *params = 0; - } - } +void Context::getInteger64v(GLenum pname, GLint64 *params) +{ + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. + switch (pname) + { + case GL_MAX_ELEMENT_INDEX: + *params = mCaps.maxElementIndex; break; - case GL_TEXTURE_BINDING_2D: + case GL_MAX_UNIFORM_BLOCK_SIZE: + *params = static_cast(mRenderer->getMaxUniformBufferSize()); + break; + case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: { - if (mState.activeSampler > mRenderer->getMaxCombinedTextureImageUnits() - 1) - { - gl::error(GL_INVALID_OPERATION); - return false; - } - - *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].id(); + GLint64 uniformBufferComponents = static_cast(mRenderer->getMaxVertexShaderUniformBuffers()) * static_cast(mRenderer->getMaxUniformBufferSize() / 4); + GLint64 defaultBufferComponents = static_cast(mRenderer->getMaxVertexUniformVectors() * 4); + *params = uniformBufferComponents + defaultBufferComponents; } break; - case GL_TEXTURE_BINDING_CUBE_MAP: + case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: { - if (mState.activeSampler > mRenderer->getMaxCombinedTextureImageUnits() - 1) - { - gl::error(GL_INVALID_OPERATION); - return false; - } - - *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id(); + GLint64 uniformBufferComponents = static_cast(mRenderer->getMaxFragmentShaderUniformBuffers()) * static_cast(mRenderer->getMaxUniformBufferSize() / 4); + GLint64 defaultBufferComponents = static_cast(mRenderer->getMaxVertexUniformVectors() * 4); + *params = uniformBufferComponents + defaultBufferComponents; } break; - case GL_RESET_NOTIFICATION_STRATEGY_EXT: - *params = mResetStrategy; - break; - case GL_NUM_PROGRAM_BINARY_FORMATS_OES: - *params = 1; - break; - case GL_PROGRAM_BINARY_FORMATS_OES: - *params = GL_PROGRAM_BINARY_ANGLE; + case GL_MAX_SERVER_WAIT_TIMEOUT: + // We do not wait for server fence objects internally, so report a max timeout of zero. + *params = 0; break; default: - return false; + UNREACHABLE(); + break; } +} - return true; +bool Context::getIndexedIntegerv(GLenum target, GLuint index, GLint *data) +{ + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. + // Indexed integer queries all refer to current state, so this function is a + // mere passthrough. + return mState.getIndexedIntegerv(target, index, data); +} + +bool Context::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) +{ + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. + // Indexed integer queries all refer to current state, so this function is a + // mere passthrough. + return mState.getIndexedInteger64v(target, index, data); } bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams) @@ -1538,7 +1078,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due // to the fact that it is stored internally as a float, and so would require conversion - // if returned from Context::getIntegerv. Since this conversion is already implemented + // if returned from Context::getIntegerv. Since this conversion is already implemented // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling // application. @@ -1549,13 +1089,13 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu *type = GL_INT; *numParams = mNumCompressedTextureFormats; } - break; + return true; case GL_SHADER_BINARY_FORMATS: { *type = GL_INT; *numParams = 0; } - break; + return true; case GL_MAX_VERTEX_ATTRIBS: case GL_MAX_VERTEX_UNIFORM_VECTORS: case GL_MAX_VARYING_VECTORS: @@ -1569,7 +1109,9 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_NUM_SHADER_BINARY_FORMATS: case GL_NUM_COMPRESSED_TEXTURE_FORMATS: case GL_ARRAY_BUFFER_BINDING: - case GL_FRAMEBUFFER_BINDING: + //case GL_FRAMEBUFFER_BINDING: // equivalent to DRAW_FRAMEBUFFER_BINDING_ANGLE + case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: + case GL_READ_FRAMEBUFFER_BINDING_ANGLE: case GL_RENDERBUFFER_BINDING: case GL_CURRENT_PROGRAM: case GL_PACK_ALIGNMENT: @@ -1625,10 +1167,24 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu *type = GL_INT; *numParams = 1; } - break; - case GL_MAX_SAMPLES_ANGLE: + return true; + case GL_MAX_SAMPLES_ANGLE: + { + if (mExtensions.framebufferMultisample) + { + *type = GL_INT; + *numParams = 1; + } + else + { + return false; + } + } + return true; + case GL_PIXEL_PACK_BUFFER_BINDING: + case GL_PIXEL_UNPACK_BUFFER_BINDING: { - if (getMaxSupportedSamples() != 0) + if (mExtensions.pixelBufferObject) { *type = GL_INT; *numParams = 1; @@ -1638,20 +1194,20 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu return false; } } - break; + return true; case GL_MAX_VIEWPORT_DIMS: { *type = GL_INT; *numParams = 2; } - break; + return true; case GL_VIEWPORT: case GL_SCISSOR_BOX: { *type = GL_INT; *numParams = 4; } - break; + return true; case GL_SHADER_COMPILER: case GL_SAMPLE_COVERAGE_INVERT: case GL_DEPTH_WRITEMASK: @@ -1669,13 +1225,13 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu *type = GL_BOOL; *numParams = 1; } - break; + return true; case GL_COLOR_WRITEMASK: { *type = GL_BOOL; *numParams = 4; } - break; + return true; case GL_POLYGON_OFFSET_FACTOR: case GL_POLYGON_OFFSET_UNITS: case GL_SAMPLE_COVERAGE_VALUE: @@ -1685,7 +1241,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu *type = GL_FLOAT; *numParams = 1; } - break; + return true; case GL_ALIASED_LINE_WIDTH_RANGE: case GL_ALIASED_POINT_SIZE_RANGE: case GL_DEPTH_RANGE: @@ -1693,49 +1249,133 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu *type = GL_FLOAT; *numParams = 2; } - break; + return true; case GL_COLOR_CLEAR_VALUE: case GL_BLEND_COLOR: { *type = GL_FLOAT; *numParams = 4; } - break; + return true; case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: - if (!supportsTextureFilterAnisotropy()) + if (!mExtensions.maxTextureAnisotropy) { return false; } *type = GL_FLOAT; *numParams = 1; - break; - default: + return true; + } + + if (mClientVersion < 3) + { return false; } - return true; + // Check for ES3.0+ parameter names + switch (pname) + { + case GL_MAX_UNIFORM_BUFFER_BINDINGS: + case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: + case GL_UNIFORM_BUFFER_BINDING: + case GL_TRANSFORM_FEEDBACK_BINDING: + case GL_COPY_READ_BUFFER_BINDING: + case GL_COPY_WRITE_BUFFER_BINDING: + case GL_TEXTURE_BINDING_3D: + case GL_TEXTURE_BINDING_2D_ARRAY: + case GL_MAX_3D_TEXTURE_SIZE: + case GL_MAX_ARRAY_TEXTURE_LAYERS: + case GL_MAX_VERTEX_UNIFORM_BLOCKS: + case GL_MAX_FRAGMENT_UNIFORM_BLOCKS: + case GL_MAX_COMBINED_UNIFORM_BLOCKS: + case GL_MAX_VARYING_COMPONENTS: + case GL_VERTEX_ARRAY_BINDING: + case GL_MAX_VERTEX_UNIFORM_COMPONENTS: + case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: + case GL_NUM_EXTENSIONS: + case GL_MAJOR_VERSION: + case GL_MINOR_VERSION: + case GL_MAX_ELEMENTS_INDICES: + case GL_MAX_ELEMENTS_VERTICES: + case GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS: + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS: + case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: + { + *type = GL_INT; + *numParams = 1; + } + return true; + + case GL_MAX_ELEMENT_INDEX: + case GL_MAX_UNIFORM_BLOCK_SIZE: + case GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS: + case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: + case GL_MAX_SERVER_WAIT_TIMEOUT: + { + *type = GL_INT_64_ANGLEX; + *numParams = 1; + } + return true; + + case GL_TRANSFORM_FEEDBACK_ACTIVE: + case GL_TRANSFORM_FEEDBACK_PAUSED: + { + *type = GL_BOOL; + *numParams = 1; + } + return true; + } + + return false; } -// Applies the render target surface, depth stencil surface, viewport rectangle and -// scissor rectangle to the renderer -bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport) +bool Context::getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams) { - Framebuffer *framebufferObject = getDrawFramebuffer(); + if (mClientVersion < 3) + { + return false; + } - if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) + switch (target) { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + case GL_UNIFORM_BUFFER_BINDING: + { + *type = GL_INT; + *numParams = 1; + } + return true; + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + case GL_UNIFORM_BUFFER_START: + case GL_UNIFORM_BUFFER_SIZE: + { + *type = GL_INT_64_ANGLEX; + *numParams = 1; + } } + return false; +} + +// Applies the render target surface, depth stencil surface, viewport rectangle and +// scissor rectangle to the renderer +bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport) +{ + Framebuffer *framebufferObject = mState.getDrawFramebuffer(); + ASSERT(framebufferObject && framebufferObject->completeness() == GL_FRAMEBUFFER_COMPLETE); + mRenderer->applyRenderTarget(framebufferObject); - if (!mRenderer->setViewport(mState.viewport, mState.zNear, mState.zFar, drawMode, mState.rasterizer.frontFace, + float nearZ, farZ; + mState.getDepthRange(&nearZ, &farZ); + if (!mRenderer->setViewport(mState.getViewport(), nearZ, farZ, drawMode, mState.getRasterizerState().frontFace, ignoreViewport)) { return false; } - mRenderer->setScissorRectangle(mState.scissor, mState.scissorTest); + mRenderer->setScissorRectangle(mState.getScissor(), mState.isScissorTestEnabled()); return true; } @@ -1743,17 +1383,22 @@ bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport) // Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device void Context::applyState(GLenum drawMode) { - Framebuffer *framebufferObject = getDrawFramebuffer(); + Framebuffer *framebufferObject = mState.getDrawFramebuffer(); int samples = framebufferObject->getSamples(); - mState.rasterizer.pointDrawMode = (drawMode == GL_POINTS); - mState.rasterizer.multiSample = (samples != 0); - mRenderer->setRasterizerState(mState.rasterizer); + RasterizerState rasterizer = mState.getRasterizerState(); + rasterizer.pointDrawMode = (drawMode == GL_POINTS); + rasterizer.multiSample = (samples != 0); + + mRenderer->setRasterizerState(rasterizer); unsigned int mask = 0; - if (mState.sampleCoverage) + if (mState.isSampleCoverageEnabled()) { - if (mState.sampleCoverageValue != 0) + GLclampf coverageValue; + bool coverageInvert = false; + mState.getSampleCoverageParams(&coverageValue, &coverageInvert); + if (coverageValue != 0) { float threshold = 0.5f; @@ -1762,7 +1407,7 @@ void Context::applyState(GLenum drawMode) { mask <<= 1; - if ((i + 1) * mState.sampleCoverageValue >= threshold) + if ((i + 1) * coverageValue >= threshold) { threshold += 1.0f; mask |= 1; @@ -1770,7 +1415,7 @@ void Context::applyState(GLenum drawMode) } } - if (mState.sampleCoverageInvert) + if (coverageInvert) { mask = ~mask; } @@ -1779,192 +1424,333 @@ void Context::applyState(GLenum drawMode) { mask = 0xFFFFFFFF; } - mRenderer->setBlendState(framebufferObject, mState.blend, mState.blendColor, mask); + mRenderer->setBlendState(framebufferObject, mState.getBlendState(), mState.getBlendColor(), mask); - mRenderer->setDepthStencilState(mState.depthStencil, mState.stencilRef, mState.stencilBackRef, - mState.rasterizer.frontFace == GL_CCW); + mRenderer->setDepthStencilState(mState.getDepthStencilState(), mState.getStencilRef(), mState.getStencilBackRef(), + rasterizer.frontFace == GL_CCW); } // Applies the shaders and shader constants to the Direct3D 9 device -void Context::applyShaders() +void Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive) { - ProgramBinary *programBinary = getCurrentProgramBinary(); + const VertexAttribute *vertexAttributes = mState.getVertexArray()->getVertexAttributes(); + + VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]; + VertexFormat::GetInputLayout(inputLayout, programBinary, vertexAttributes, mState.getVertexAttribCurrentValues()); + + const Framebuffer *fbo = mState.getDrawFramebuffer(); + + mRenderer->applyShaders(programBinary, inputLayout, fbo, mState.getRasterizerState().rasterizerDiscard, transformFeedbackActive); - mRenderer->applyShaders(programBinary); - programBinary->applyUniforms(); } -// Applies the textures and sampler states to the Direct3D 9 device -void Context::applyTextures() +size_t Context::getCurrentTexturesAndSamplerStates(ProgramBinary *programBinary, SamplerType type, Texture **outTextures, + TextureType *outTextureTypes, SamplerState *outSamplers) { - applyTextures(SAMPLER_PIXEL); + 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 + if (textureUnit != -1) + { + outTextures[i] = getSamplerTexture(textureUnit, outTextureTypes[i]); + outTextures[i]->getSamplerStateWithNativeOffset(&outSamplers[i]); + Sampler *samplerObject = mState.getSampler(textureUnit); + if (samplerObject) + { + samplerObject->getState(&outSamplers[i]); + } + } + else + { + outTextures[i] = NULL; + } + } - if (mSupportsVertexTexture) + return samplerRange; +} + +void Context::generateSwizzles(Texture *textures[], size_t count) +{ + for (size_t i = 0; i < count; i++) { - applyTextures(SAMPLER_VERTEX); + if (textures[i] && textures[i]->getSamplerState().swizzleRequired()) + { + mRenderer->generateSwizzle(textures[i]); + } } } -// For each Direct3D 9 sampler of either the pixel or vertex stage, +// 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 type) +void Context::applyTextures(SamplerType shaderType, Texture *textures[], TextureType *textureTypes, SamplerState *samplers, + size_t textureCount, const FramebufferTextureSerialArray& framebufferSerials, + size_t framebufferSerialCount) { - ProgramBinary *programBinary = getCurrentProgramBinary(); - - FramebufferTextureSerialSet boundFramebufferTextures = getBoundFramebufferTextureSerials(); - // Range of Direct3D samplers of given sampler type - int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : mRenderer->getMaxVertexTextureImageUnits(); - int samplerRange = programBinary->getUsedSamplerRange(type); + size_t samplerCount = (shaderType == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS + : mRenderer->getMaxVertexTextureImageUnits(); - for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++) + for (size_t samplerIndex = 0; samplerIndex < textureCount; samplerIndex++) { - int textureUnit = programBinary->getSamplerMapping(type, samplerIndex); // OpenGL texture image unit index + Texture *texture = textures[samplerIndex]; + const SamplerState &sampler = samplers[samplerIndex]; + TextureType textureType = textureTypes[samplerIndex]; - if (textureUnit != -1) + if (texture) { - TextureType textureType = programBinary->getSamplerTextureType(type, samplerIndex); - Texture *texture = getSamplerTexture(textureUnit, textureType); - - if (texture->isSamplerComplete() && - boundFramebufferTextures.find(texture->getTextureSerial()) == boundFramebufferTextures.end()) + // TODO: std::binary_search may become unavailable using older versions of GCC + if (texture->isSamplerComplete(sampler) && + !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial())) { - SamplerState samplerState; - texture->getSamplerState(&samplerState); - mRenderer->setSamplerState(type, samplerIndex, samplerState); - - mRenderer->setTexture(type, samplerIndex, texture); - + mRenderer->setSamplerState(shaderType, samplerIndex, sampler); + mRenderer->setTexture(shaderType, samplerIndex, texture); texture->resetDirty(); } else { - mRenderer->setTexture(type, samplerIndex, getIncompleteTexture(textureType)); + Texture *incompleteTexture = getIncompleteTexture(textureType); + mRenderer->setTexture(shaderType, samplerIndex, incompleteTexture); + incompleteTexture->resetDirty(); } } else { - mRenderer->setTexture(type, samplerIndex, NULL); + mRenderer->setTexture(shaderType, samplerIndex, NULL); } } - for (int samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++) + for (size_t samplerIndex = textureCount; samplerIndex < samplerCount; samplerIndex++) { - mRenderer->setTexture(type, samplerIndex, NULL); + mRenderer->setTexture(shaderType, samplerIndex, NULL); } } -void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, - GLenum format, GLenum type, GLsizei *bufSize, void* pixels) +bool Context::applyUniformBuffers() { - Framebuffer *framebuffer = getReadFramebuffer(); + Program *programObject = getProgram(mState.getCurrentProgramId()); + ProgramBinary *programBinary = programObject->getProgramBinary(); + + std::vector boundBuffers; - if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < programBinary->getActiveUniformBlockCount(); uniformBlockIndex++) { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); + GLuint blockBinding = programObject->getUniformBlockBinding(uniformBlockIndex); + + if (mState.getIndexedUniformBuffer(blockBinding)->id() == 0) + { + // undefined behaviour + return false; + } + else + { + Buffer *uniformBuffer = mState.getIndexedUniformBuffer(blockBinding); + ASSERT(uniformBuffer); + boundBuffers.push_back(uniformBuffer); + } } - if (getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0) + return programBinary->applyUniformBuffers(boundBuffers); +} + +bool Context::applyTransformFeedbackBuffers() +{ + TransformFeedback *curTransformFeedback = mState.getCurrentTransformFeedback(); + if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) + { + Buffer *transformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; + GLintptr transformFeedbackOffsets[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; + for (size_t i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + { + transformFeedbackBuffers[i] = mState.getIndexedTransformFeedbackBuffer(i); + transformFeedbackOffsets[i] = mState.getIndexedTransformFeedbackBufferOffset(i); + } + mRenderer->applyTransformFeedbackBuffers(transformFeedbackBuffers, transformFeedbackOffsets); + return true; + } + else { - return gl::error(GL_INVALID_OPERATION); + return false; } +} - GLsizei outputPitch = ComputePitch(width, ConvertSizedInternalFormat(format, type), getPackAlignment()); - // sized query sanity check - if (bufSize) +void Context::markTransformFeedbackUsage() +{ + for (size_t i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) { - int requiredSize = outputPitch * height; - if (requiredSize > *bufSize) + Buffer *buffer = mState.getIndexedTransformFeedbackBuffer(i); + if (buffer) { - return gl::error(GL_INVALID_OPERATION); + buffer->markTransformFeedbackUsage(); } } - - mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, getPackReverseRowOrder(), getPackAlignment(), pixels); } void Context::clear(GLbitfield mask) { - Framebuffer *framebufferObject = getDrawFramebuffer(); + if (mState.isRasterizerDiscardEnabled()) + { + return; + } + + ClearParameters clearParams = mState.getClearParameters(mask); - if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) + if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); + return; } - DWORD flags = 0; - GLbitfield finalMask = 0; + mRenderer->clear(clearParams, mState.getDrawFramebuffer()); +} - if (mask & GL_COLOR_BUFFER_BIT) +void Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values) +{ + if (mState.isRasterizerDiscardEnabled()) { - mask &= ~GL_COLOR_BUFFER_BIT; + return; + } - if (framebufferObject->hasEnabledColorAttachment()) + // glClearBufferfv can be called to clear the color buffer or depth buffer + ClearParameters clearParams = mState.getClearParameters(0); + + if (buffer == GL_COLOR) + { + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) { - finalMask |= GL_COLOR_BUFFER_BIT; + clearParams.clearColor[i] = (drawbuffer == static_cast(i)); } + clearParams.colorFClearValue = ColorF(values[0], values[1], values[2], values[3]); + clearParams.colorClearType = GL_FLOAT; + } + + if (buffer == GL_DEPTH) + { + clearParams.clearDepth = true; + clearParams.depthClearValue = values[0]; + } + + if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport + { + return; + } + + mRenderer->clear(clearParams, mState.getDrawFramebuffer()); +} + +void Context::clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values) +{ + if (mState.isRasterizerDiscardEnabled()) + { + return; + } + + // glClearBufferuv can only be called to clear a color buffer + ClearParameters clearParams = mState.getClearParameters(0); + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = (drawbuffer == static_cast(i)); + } + 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; + } + + mRenderer->clear(clearParams, mState.getDrawFramebuffer()); +} + +void Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values) +{ + if (mState.isRasterizerDiscardEnabled()) + { + return; } - if (mask & GL_DEPTH_BUFFER_BIT) + // glClearBufferfv can be called to clear the color buffer or stencil buffer + ClearParameters clearParams = mState.getClearParameters(0); + + if (buffer == GL_COLOR) { - mask &= ~GL_DEPTH_BUFFER_BIT; - if (mState.depthStencil.depthMask && framebufferObject->getDepthbufferType() != GL_NONE) + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) { - finalMask |= GL_DEPTH_BUFFER_BIT; + clearParams.clearColor[i] = (drawbuffer == static_cast(i)); } + clearParams.colorIClearValue = ColorI(values[0], values[1], values[2], values[3]); + clearParams.colorClearType = GL_INT; } - if (mask & GL_STENCIL_BUFFER_BIT) + if (buffer == GL_STENCIL) { - mask &= ~GL_STENCIL_BUFFER_BIT; - if (framebufferObject->getStencilbufferType() != GL_NONE) - { - rx::RenderTarget *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - return; - } + clearParams.clearStencil = true; + clearParams.stencilClearValue = values[1]; + } - if (GetStencilSize(depthStencil->getActualFormat()) > 0) - { - finalMask |= GL_STENCIL_BUFFER_BIT; - } - } + if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport + { + return; } - if (mask != 0) + mRenderer->clear(clearParams, mState.getDrawFramebuffer()); +} + +void Context::clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil) +{ + if (mState.isRasterizerDiscardEnabled()) { - return gl::error(GL_INVALID_VALUE); + return; } + // glClearBufferfi can only be called to clear a depth stencil buffer + ClearParameters clearParams = mState.getClearParameters(0); + clearParams.clearDepth = true; + clearParams.depthClearValue = depth; + clearParams.clearStencil = true; + clearParams.stencilClearValue = stencil; + if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport { return; } - ClearParameters clearParams; - clearParams.mask = finalMask; - clearParams.colorClearValue = mState.colorClearValue; - clearParams.colorMaskRed = mState.blend.colorMaskRed; - clearParams.colorMaskGreen = mState.blend.colorMaskGreen; - clearParams.colorMaskBlue = mState.blend.colorMaskBlue; - clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha; - clearParams.depthClearValue = mState.depthClearValue; - clearParams.stencilClearValue = mState.stencilClearValue; - clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask; + mRenderer->clear(clearParams, mState.getDrawFramebuffer()); +} + +void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLsizei *bufSize, void* pixels) +{ + gl::Framebuffer *framebuffer = mState.getReadFramebuffer(); + + bool isSized = IsSizedInternalFormat(format); + GLenum sizedInternalFormat = (isSized ? format : GetSizedInternalFormat(format, type)); + GLuint outputPitch = GetRowPitch(sizedInternalFormat, type, width, mState.getPackAlignment()); - mRenderer->clear(clearParams, framebufferObject); + mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, mState.getPackState(), pixels); } void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances) { - if (!mState.currentProgram) - { - return gl::error(GL_INVALID_OPERATION); - } + 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); if (!mRenderer->applyPrimitiveType(mode, count)) { @@ -1978,40 +1764,58 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan applyState(mode); - ProgramBinary *programBinary = getCurrentProgramBinary(); - - GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, first, count, instances); + GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.getVertexArray()->getVertexAttributes(), mState.getVertexAttribCurrentValues(), first, count, instances); if (err != GL_NO_ERROR) { return gl::error(err); } - applyShaders(); - applyTextures(); + bool transformFeedbackActive = applyTransformFeedbackBuffers(); + + applyShaders(programBinary, transformFeedbackActive); + + FramebufferTextureSerialArray frameBufferSerials; + size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&frameBufferSerials); + + applyTextures(SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers, vsTextureCount, frameBufferSerials, framebufferSerialCount); + applyTextures(SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers, psTextureCount, frameBufferSerials, framebufferSerialCount); - if (!programBinary->validateSamplers(NULL)) + if (!applyUniformBuffers()) { - return gl::error(GL_INVALID_OPERATION); + return; } if (!skipDraw(mode)) { - mRenderer->drawArrays(mode, count, instances); + mRenderer->drawArrays(mode, count, instances, transformFeedbackActive); + + if (transformFeedbackActive) + { + markTransformFeedbackUsage(); + } } } void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances) { - if (!mState.currentProgram) - { - return gl::error(GL_INVALID_OPERATION); - } + 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); - if (!indices && !mState.elementArrayBuffer) - { - return gl::error(GL_INVALID_OPERATION); - } - if (!mRenderer->applyPrimitiveType(mode, count)) { return; @@ -2024,33 +1828,42 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid applyState(mode); + VertexArray *vao = mState.getVertexArray(); rx::TranslatedIndexData indexInfo; - GLenum err = mRenderer->applyIndexBuffer(indices, mState.elementArrayBuffer.get(), count, mode, type, &indexInfo); + GLenum err = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo); if (err != GL_NO_ERROR) { return gl::error(err); } - ProgramBinary *programBinary = getCurrentProgramBinary(); - GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; - err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, indexInfo.minIndex, vertexCount, instances); + err = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(), mState.getVertexAttribCurrentValues(), indexInfo.minIndex, vertexCount, instances); if (err != GL_NO_ERROR) { return gl::error(err); } - applyShaders(); - applyTextures(); + bool transformFeedbackActive = applyTransformFeedbackBuffers(); + // Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation + // layer. + ASSERT(!transformFeedbackActive); + + applyShaders(programBinary, transformFeedbackActive); + + FramebufferTextureSerialArray frameBufferSerials; + size_t framebufferSerialCount = getBoundFramebufferTextureSerials(&frameBufferSerials); + + applyTextures(SAMPLER_VERTEX, vsTextures, vsTextureTypes, vsSamplers, vsTextureCount, frameBufferSerials, framebufferSerialCount); + applyTextures(SAMPLER_PIXEL, psTextures, psTextureTypes, psSamplers, psTextureCount, frameBufferSerials, framebufferSerialCount); - if (!programBinary->validateSamplers(NULL)) + if (!applyUniformBuffers()) { - return gl::error(GL_INVALID_OPERATION); + return; } if (!skipDraw(mode)) { - mRenderer->drawElements(mode, count, type, indices, mState.elementArrayBuffer.get(), indexInfo, instances); + mRenderer->drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances); } } @@ -2146,254 +1959,139 @@ GLenum Context::getResetStatus() { mResetStatus = GL_NO_ERROR; } - } - - return status; -} - -bool Context::isResetNotificationEnabled() -{ - return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT); -} - -int Context::getMajorShaderModel() const -{ - return mMajorShaderModel; -} - -float Context::getMaximumPointSize() const -{ - return mMaximumPointSize; -} - -unsigned int Context::getMaximumCombinedTextureImageUnits() const -{ - return mRenderer->getMaxCombinedTextureImageUnits(); -} - -int Context::getMaxSupportedSamples() const -{ - return mRenderer->getMaxSupportedSamples(); -} - -unsigned int Context::getMaximumRenderTargets() const -{ - return mRenderer->getMaxRenderTargets(); -} - -bool Context::supportsEventQueries() const -{ - return mSupportsEventQueries; -} - -bool Context::supportsOcclusionQueries() const -{ - return mSupportsOcclusionQueries; -} - -bool Context::supportsBGRATextures() const -{ - return mSupportsBGRATextures; -} - -bool Context::supportsDXT1Textures() const -{ - return mSupportsDXT1Textures; -} - -bool Context::supportsDXT3Textures() const -{ - return mSupportsDXT3Textures; -} - -bool Context::supportsDXT5Textures() const -{ - return mSupportsDXT5Textures; -} + } -bool Context::supportsFloat32Textures() const -{ - return mSupportsFloat32Textures; + return status; } -bool Context::supportsFloat32LinearFilter() const +bool Context::isResetNotificationEnabled() { - return mSupportsFloat32LinearFilter; + return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT); } -bool Context::supportsFloat32RenderableTextures() const +int Context::getClientVersion() const { - return mSupportsFloat32RenderableTextures; + return mClientVersion; } -bool Context::supportsFloat16Textures() const +const Caps &Context::getCaps() const { - return mSupportsFloat16Textures; + return mCaps; } -bool Context::supportsFloat16LinearFilter() const +const TextureCapsMap &Context::getTextureCaps() const { - return mSupportsFloat16LinearFilter; + return mTextureCaps; } -bool Context::supportsFloat16RenderableTextures() const +const Extensions &Context::getExtensions() const { - return mSupportsFloat16RenderableTextures; + return mExtensions; } -int Context::getMaximumRenderbufferDimension() const +int Context::getMajorShaderModel() const { - return mMaxRenderbufferDimension; + return mMajorShaderModel; } -int Context::getMaximumTextureDimension() const +unsigned int Context::getMaximumCombinedTextureImageUnits() const { - return mMaxTextureDimension; + return mRenderer->getMaxCombinedTextureImageUnits(); } -int Context::getMaximumCubeTextureDimension() const +unsigned int Context::getMaximumCombinedUniformBufferBindings() const { - return mMaxCubeTextureDimension; + return mRenderer->getMaxVertexShaderUniformBuffers() + + mRenderer->getMaxFragmentShaderUniformBuffers(); } -int Context::getMaximumTextureLevel() const +int Context::getMaxSupportedSamples() const { - return mMaxTextureLevel; + return mRenderer->getMaxSupportedSamples(); } -bool Context::supportsLuminanceTextures() const +GLsizei Context::getMaxSupportedFormatSamples(GLenum internalFormat) const { - return mSupportsLuminanceTextures; + return mRenderer->getMaxSupportedFormatSamples(internalFormat); } -bool Context::supportsLuminanceAlphaTextures() const +GLsizei Context::getNumSampleCounts(GLenum internalFormat) const { - return mSupportsLuminanceAlphaTextures; + return mRenderer->getNumSampleCounts(internalFormat); } -bool Context::supportsDepthTextures() const +void Context::getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const { - return mSupportsDepthTextures; + mRenderer->getSampleCounts(internalFormat, bufSize, params); } -bool Context::supports32bitIndices() const +unsigned int Context::getMaxTransformFeedbackBufferBindings() const { - return mSupports32bitIndices; + return mRenderer->getMaxTransformFeedbackBuffers(); } -bool Context::supportsNonPower2Texture() const +GLintptr Context::getUniformBufferOffsetAlignment() const { - return mSupportsNonPower2Texture; + // setting a large alignment forces uniform buffers to bind with zero offset + return static_cast(std::numeric_limits::max()); } -bool Context::supportsInstancing() const +void Context::getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type) { - return mSupportsInstancing; -} + Framebuffer *framebuffer = mState.getReadFramebuffer(); + ASSERT(framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE); -bool Context::supportsTextureFilterAnisotropy() const -{ - return mSupportsTextureFilterAnisotropy; -} + FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); + ASSERT(attachment); -float Context::getTextureMaxAnisotropy() const -{ - return mMaxTextureAnisotropy; + *internalFormat = attachment->getActualFormat(); + *format = gl::GetFormat(attachment->getActualFormat()); + *type = gl::GetType(attachment->getActualFormat()); } -bool Context::getCurrentReadFormatType(GLenum *format, GLenum *type) +void Context::detachTexture(GLuint texture) { - Framebuffer *framebuffer = getReadFramebuffer(); - if (!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) - { - return gl::error(GL_INVALID_OPERATION, false); - } - - Renderbuffer *renderbuffer = framebuffer->getReadColorbuffer(); - if (!renderbuffer) - { - return gl::error(GL_INVALID_OPERATION, false); - } - - *format = gl::ExtractFormat(renderbuffer->getActualFormat()); - *type = gl::ExtractType(renderbuffer->getActualFormat()); - - return true; + // Simple pass-through to State's detachTexture method, as textures do not require + // allocation map management either here or in the resource manager at detach time. + // Zero textures are held by the Context, and we don't attempt to request them from + // the State. + mState.detachTexture(texture); } void Context::detachBuffer(GLuint buffer) { + // Buffer detachment is handled by Context, because the buffer must also be + // attached from any VAOs in existence, and Context holds the VAO map. + // [OpenGL ES 2.0.24] section 2.9 page 22: // If a buffer object is deleted while it is bound, all bindings to that object in the current context // (i.e. in the thread that called Delete-Buffers) are reset to zero. - if (mState.arrayBuffer.id() == buffer) - { - mState.arrayBuffer.set(NULL); - } - - if (mState.elementArrayBuffer.id() == buffer) - { - mState.elementArrayBuffer.set(NULL); - } - - for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++) - { - if (mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer) - { - mState.vertexAttribute[attribute].mBoundBuffer.set(NULL); - } - } -} - -void Context::detachTexture(GLuint texture) -{ - // [OpenGL ES 2.0.24] section 3.8 page 84: - // If a texture object is deleted, it is as if all texture units which are bound to that texture object are - // rebound to texture object zero - - for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) - { - for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) - { - if (mState.samplerTexture[type][sampler].id() == texture) - { - mState.samplerTexture[type][sampler].set(NULL); - } - } - } - - // [OpenGL ES 2.0.24] section 4.4 page 112: - // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is - // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this - // image was attached in the currently bound framebuffer. + mState.removeArrayBufferBinding(buffer); - Framebuffer *readFramebuffer = getReadFramebuffer(); - Framebuffer *drawFramebuffer = getDrawFramebuffer(); - - if (readFramebuffer) - { - readFramebuffer->detachTexture(texture); - } - - if (drawFramebuffer && drawFramebuffer != readFramebuffer) + // mark as freed among the vertex array objects + for (auto vaoIt = mVertexArrayMap.begin(); vaoIt != mVertexArrayMap.end(); vaoIt++) { - drawFramebuffer->detachTexture(texture); + vaoIt->second->detachBuffer(buffer); } } void Context::detachFramebuffer(GLuint framebuffer) { + // Framebuffer detachment is handled by Context, because 0 is a valid + // Framebuffer object, and a pointer to it must be passed from Context + // to State at binding time. + // [OpenGL ES 2.0.24] section 4.4 page 107: // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero. - if (mState.readFramebuffer == framebuffer) + if (mState.removeReadFramebufferBinding(framebuffer)) { bindReadFramebuffer(0); } - if (mState.drawFramebuffer == framebuffer) + if (mState.removeDrawFramebufferBinding(framebuffer)) { bindDrawFramebuffer(0); } @@ -2401,32 +2099,32 @@ void Context::detachFramebuffer(GLuint framebuffer) void Context::detachRenderbuffer(GLuint renderbuffer) { - // [OpenGL ES 2.0.24] section 4.4 page 109: - // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer - // had been executed with the target RENDERBUFFER and name of zero. - - if (mState.renderbuffer.id() == renderbuffer) - { - bindRenderbuffer(0); - } - - // [OpenGL ES 2.0.24] section 4.4 page 111: - // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer, - // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment - // point to which this image was attached in the currently bound framebuffer. + mState.detachRenderbuffer(renderbuffer); +} - Framebuffer *readFramebuffer = getReadFramebuffer(); - Framebuffer *drawFramebuffer = getDrawFramebuffer(); +void Context::detachVertexArray(GLuint vertexArray) +{ + // Vertex array detachment is handled by Context, because 0 is a valid + // VAO, and a pointer to it must be passed from Context to State at + // binding time. - if (readFramebuffer) + // [OpenGL ES 3.0.2] section 2.10 page 43: + // If a vertex array object that is currently bound is deleted, the binding + // for that object reverts to zero and the default vertex array becomes current. + if (mState.removeVertexArrayBinding(vertexArray)) { - readFramebuffer->detachRenderbuffer(renderbuffer); + bindVertexArray(0); } +} - if (drawFramebuffer && drawFramebuffer != readFramebuffer) - { - drawFramebuffer->detachRenderbuffer(renderbuffer); - } +void Context::detachTransformFeedback(GLuint transformFeedback) +{ + mState.detachTransformFeedback(transformFeedback); +} + +void Context::detachSampler(GLuint sampler) +{ + mState.detachSampler(sampler); } Texture *Context::getIncompleteTexture(TextureType type) @@ -2435,7 +2133,8 @@ Texture *Context::getIncompleteTexture(TextureType type) if (t == NULL) { - static const GLubyte color[] = { 0, 0, 0, 255 }; + const GLubyte color[] = { 0, 0, 0, 255 }; + const PixelUnpackState incompleteUnpackState(1); switch (type) { @@ -2445,26 +2144,44 @@ Texture *Context::getIncompleteTexture(TextureType type) case TEXTURE_2D: { - Texture2D *incomplete2d = new Texture2D(mRenderer, Texture::INCOMPLETE_TEXTURE_ID); - incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); + Texture2D *incomplete2d = new Texture2D(mRenderer->createTexture2D(), Texture::INCOMPLETE_TEXTURE_ID); + incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); t = incomplete2d; } break; case TEXTURE_CUBE: { - TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer, Texture::INCOMPLETE_TEXTURE_ID); + TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer->createTextureCube(), Texture::INCOMPLETE_TEXTURE_ID); - incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); - incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); - incompleteCube->setImagePosY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); - incompleteCube->setImageNegY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); - incompleteCube->setImagePosZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); - incompleteCube->setImageNegZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color); + 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); + incompleteCube->setImagePosY(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + incompleteCube->setImageNegY(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + incompleteCube->setImagePosZ(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + incompleteCube->setImageNegZ(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); t = incompleteCube; } break; + + case TEXTURE_3D: + { + Texture3D *incomplete3d = new Texture3D(mRenderer->createTexture3D(), 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: + { + Texture2DArray *incomplete2darray = new Texture2DArray(mRenderer->createTexture2DArray(), Texture::INCOMPLETE_TEXTURE_ID); + incomplete2darray->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); + + t = incomplete2darray; + } + break; } mIncompleteTextures[type].set(t); @@ -2480,9 +2197,9 @@ bool Context::skipDraw(GLenum drawMode) // ProgramBinary assumes non-point rendering if gl_PointSize isn't written, // which affects varying interpolation. Since the value of gl_PointSize is // undefined when not written, just skip drawing to avoid unexpected results. - if (!getCurrentProgramBinary()->usesPointSize()) + if (!mState.getCurrentProgramBinary()->usesPointSize()) { - // This is stictly speaking not an error, but developers should be + // This is stictly speaking not an error, but developers should be // notified of risking undefined behavior. ERR("Point rendering without writing to gl_PointSize."); @@ -2491,7 +2208,7 @@ bool Context::skipDraw(GLenum drawMode) } else if (IsTriangleMode(drawMode)) { - if (mState.rasterizer.cullFace && mState.rasterizer.cullMode == GL_FRONT_AND_BACK) + if (mState.getRasterizerState().cullFace && mState.getRasterizerState().cullMode == GL_FRONT_AND_BACK) { return true; } @@ -2500,148 +2217,97 @@ bool Context::skipDraw(GLenum drawMode) return false; } -void Context::setVertexAttrib(GLuint index, const GLfloat *values) -{ - ASSERT(index < gl::MAX_VERTEX_ATTRIBS); - - mState.vertexAttribute[index].mCurrentValue[0] = values[0]; - mState.vertexAttribute[index].mCurrentValue[1] = values[1]; - mState.vertexAttribute[index].mCurrentValue[2] = values[2]; - mState.vertexAttribute[index].mCurrentValue[3] = values[3]; -} - void Context::setVertexAttribDivisor(GLuint index, GLuint divisor) { - ASSERT(index < gl::MAX_VERTEX_ATTRIBS); - - mState.vertexAttribute[index].mDivisor = divisor; + mState.getVertexArray()->setVertexAttribDivisor(index, divisor); } -// keep list sorted in following order -// OES extensions -// EXT extensions -// Vendor extensions -void Context::initExtensionString() +void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param) { - std::string extensionString = ""; - - // OES extensions - if (supports32bitIndices()) - { - extensionString += "GL_OES_element_index_uint "; - } - - extensionString += "GL_OES_packed_depth_stencil "; - extensionString += "GL_OES_get_program_binary "; - extensionString += "GL_OES_rgb8_rgba8 "; - if (mRenderer->getDerivativeInstructionSupport()) - { - extensionString += "GL_OES_standard_derivatives "; - } - - if (supportsFloat16Textures()) - { - extensionString += "GL_OES_texture_half_float "; - } - if (supportsFloat16LinearFilter()) - { - extensionString += "GL_OES_texture_half_float_linear "; - } - if (supportsFloat32Textures()) - { - extensionString += "GL_OES_texture_float "; - } - if (supportsFloat32LinearFilter()) - { - extensionString += "GL_OES_texture_float_linear "; - } + mResourceManager->checkSamplerAllocation(sampler); - if (supportsNonPower2Texture()) - { - extensionString += "GL_OES_texture_npot "; - } - - // Multi-vendor (EXT) extensions - if (supportsOcclusionQueries()) - { - extensionString += "GL_EXT_occlusion_query_boolean "; - } - - extensionString += "GL_EXT_read_format_bgra "; - extensionString += "GL_EXT_robustness "; - - if (supportsDXT1Textures()) - { - extensionString += "GL_EXT_texture_compression_dxt1 "; - } - - if (supportsTextureFilterAnisotropy()) - { - extensionString += "GL_EXT_texture_filter_anisotropic "; - } + Sampler *samplerObject = getSampler(sampler); + ASSERT(samplerObject); - if (supportsBGRATextures()) - { - extensionString += "GL_EXT_texture_format_BGRA8888 "; - } - - if (mRenderer->getMaxRenderTargets() > 1) + switch (pname) { - extensionString += "GL_EXT_draw_buffers "; + case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(static_cast(param)); break; + case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(static_cast(param)); break; + case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(static_cast(param)); break; + case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(static_cast(param)); break; + case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(static_cast(param)); break; + case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(static_cast(param)); break; + case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(static_cast(param)); break; + case GL_TEXTURE_COMPARE_MODE: samplerObject->setComparisonMode(static_cast(param)); break; + case GL_TEXTURE_COMPARE_FUNC: samplerObject->setComparisonFunc(static_cast(param)); break; + default: UNREACHABLE(); break; } +} - extensionString += "GL_EXT_texture_storage "; - extensionString += "GL_EXT_frag_depth "; +void Context::samplerParameterf(GLuint sampler, GLenum pname, GLfloat param) +{ + mResourceManager->checkSamplerAllocation(sampler); - // ANGLE-specific extensions - if (supportsDepthTextures()) - { - extensionString += "GL_ANGLE_depth_texture "; - } + Sampler *samplerObject = getSampler(sampler); + ASSERT(samplerObject); - extensionString += "GL_ANGLE_framebuffer_blit "; - if (getMaxSupportedSamples() != 0) + switch (pname) { - extensionString += "GL_ANGLE_framebuffer_multisample "; + case GL_TEXTURE_MIN_FILTER: samplerObject->setMinFilter(uiround(param)); break; + case GL_TEXTURE_MAG_FILTER: samplerObject->setMagFilter(uiround(param)); break; + case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(uiround(param)); break; + case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(uiround(param)); break; + case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(uiround(param)); break; + case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(param); break; + case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(param); break; + case GL_TEXTURE_COMPARE_MODE: samplerObject->setComparisonMode(uiround(param)); break; + case GL_TEXTURE_COMPARE_FUNC: samplerObject->setComparisonFunc(uiround(param)); break; + default: UNREACHABLE(); break; } +} - if (supportsInstancing()) - { - extensionString += "GL_ANGLE_instanced_arrays "; - } +GLint Context::getSamplerParameteri(GLuint sampler, GLenum pname) +{ + mResourceManager->checkSamplerAllocation(sampler); - extensionString += "GL_ANGLE_pack_reverse_row_order "; + Sampler *samplerObject = getSampler(sampler); + ASSERT(samplerObject); - if (supportsDXT3Textures()) - { - extensionString += "GL_ANGLE_texture_compression_dxt3 "; - } - if (supportsDXT5Textures()) + switch (pname) { - extensionString += "GL_ANGLE_texture_compression_dxt5 "; + case GL_TEXTURE_MIN_FILTER: return static_cast(samplerObject->getMinFilter()); + case GL_TEXTURE_MAG_FILTER: return static_cast(samplerObject->getMagFilter()); + case GL_TEXTURE_WRAP_S: return static_cast(samplerObject->getWrapS()); + case GL_TEXTURE_WRAP_T: return static_cast(samplerObject->getWrapT()); + case GL_TEXTURE_WRAP_R: return static_cast(samplerObject->getWrapR()); + case GL_TEXTURE_MIN_LOD: return uiround(samplerObject->getMinLod()); + case GL_TEXTURE_MAX_LOD: return uiround(samplerObject->getMaxLod()); + case GL_TEXTURE_COMPARE_MODE: return static_cast(samplerObject->getComparisonMode()); + case GL_TEXTURE_COMPARE_FUNC: return static_cast(samplerObject->getComparisonFunc()); + default: UNREACHABLE(); return 0; } +} - extensionString += "GL_ANGLE_texture_usage "; - extensionString += "GL_ANGLE_translated_shader_source "; +GLfloat Context::getSamplerParameterf(GLuint sampler, GLenum pname) +{ + mResourceManager->checkSamplerAllocation(sampler); - // Other vendor-specific extensions - if (supportsEventQueries()) - { - extensionString += "GL_NV_fence "; - } + Sampler *samplerObject = getSampler(sampler); + ASSERT(samplerObject); - std::string::size_type end = extensionString.find_last_not_of(' '); - if (end != std::string::npos) + switch (pname) { - extensionString.resize(end+1); + case GL_TEXTURE_MIN_FILTER: return static_cast(samplerObject->getMinFilter()); + case GL_TEXTURE_MAG_FILTER: return static_cast(samplerObject->getMagFilter()); + case GL_TEXTURE_WRAP_S: return static_cast(samplerObject->getWrapS()); + case GL_TEXTURE_WRAP_T: return static_cast(samplerObject->getWrapT()); + case GL_TEXTURE_WRAP_R: return static_cast(samplerObject->getWrapR()); + case GL_TEXTURE_MIN_LOD: return samplerObject->getMinLod(); + case GL_TEXTURE_MAX_LOD: return samplerObject->getMaxLod(); + case GL_TEXTURE_COMPARE_MODE: return static_cast(samplerObject->getComparisonMode()); + case GL_TEXTURE_COMPARE_FUNC: return static_cast(samplerObject->getComparisonFunc()); + default: UNREACHABLE(); return 0; } - - mExtensionString = makeStaticString(extensionString); -} - -const char *Context::getExtensionString() const -{ - return mExtensionString; } void Context::initRendererString() @@ -2651,319 +2317,226 @@ void Context::initRendererString() rendererString << mRenderer->getRendererDescription(); rendererString << ")"; - mRendererString = makeStaticString(rendererString.str()); + mRendererString = MakeStaticString(rendererString.str()); } -const char *Context::getRendererString() const +const std::string &Context::getRendererString() const { return mRendererString; } -Context::FramebufferTextureSerialSet Context::getBoundFramebufferTextureSerials() +void Context::initExtensionStrings() { - FramebufferTextureSerialSet set; - - Framebuffer *drawFramebuffer = getDrawFramebuffer(); - for (unsigned int i = 0; i < IMPLEMENTATION_MAX_DRAW_BUFFERS; i++) - { - Renderbuffer *renderBuffer = drawFramebuffer->getColorbuffer(i); - if (renderBuffer && renderBuffer->getTextureSerial() != 0) - { - set.insert(renderBuffer->getTextureSerial()); - } - } + mExtensionStrings = mExtensions.getStrings(); - Renderbuffer *depthStencilBuffer = drawFramebuffer->getDepthOrStencilbuffer(); - if (depthStencilBuffer && depthStencilBuffer->getTextureSerial() != 0) - { - set.insert(depthStencilBuffer->getTextureSerial()); - } - - return set; + std::ostringstream combinedStringStream; + std::copy(mExtensionStrings.begin(), mExtensionStrings.end(), std::ostream_iterator(combinedStringStream, " ")); + mExtensionString = combinedStringStream.str(); } -void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask) +const std::string &Context::getExtensionString() const { - Framebuffer *readFramebuffer = getReadFramebuffer(); - Framebuffer *drawFramebuffer = getDrawFramebuffer(); - - if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE || - !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) - { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); - } - - if (drawFramebuffer->getSamples() != 0) - { - return gl::error(GL_INVALID_OPERATION); - } - - Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer(); - Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer(); - - if (drawColorBuffer == NULL) - { - ERR("Draw buffers formats don't match, which is not supported in this implementation of BlitFramebufferANGLE"); - return gl::error(GL_INVALID_OPERATION); - } - - int readBufferWidth = readColorBuffer->getWidth(); - int readBufferHeight = readColorBuffer->getHeight(); - int drawBufferWidth = drawColorBuffer->getWidth(); - int drawBufferHeight = drawColorBuffer->getHeight(); - - Rectangle sourceRect; - Rectangle destRect; + return mExtensionString; +} - if (srcX0 < srcX1) - { - sourceRect.x = srcX0; - destRect.x = dstX0; - sourceRect.width = srcX1 - srcX0; - destRect.width = dstX1 - dstX0; - } - else - { - sourceRect.x = srcX1; - destRect.x = dstX1; - sourceRect.width = srcX0 - srcX1; - destRect.width = dstX0 - dstX1; - } +const std::string &Context::getExtensionString(size_t idx) const +{ + return mExtensionStrings[idx]; +} - if (srcY0 < srcY1) - { - sourceRect.height = srcY1 - srcY0; - destRect.height = dstY1 - dstY0; - sourceRect.y = srcY0; - destRect.y = dstY0; - } - else - { - sourceRect.height = srcY0 - srcY1; - destRect.height = dstY0 - srcY1; - sourceRect.y = srcY1; - destRect.y = dstY1; - } +size_t Context::getExtensionStringCount() const +{ + return mExtensionStrings.size(); +} - Rectangle sourceScissoredRect = sourceRect; - Rectangle destScissoredRect = destRect; +size_t Context::getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray) +{ + size_t serialCount = 0; - if (mState.scissorTest) + Framebuffer *drawFramebuffer = mState.getDrawFramebuffer(); + for (unsigned int i = 0; i < IMPLEMENTATION_MAX_DRAW_BUFFERS; i++) { - // Only write to parts of the destination framebuffer which pass the scissor test. - if (destRect.x < mState.scissor.x) - { - int xDiff = mState.scissor.x - destRect.x; - destScissoredRect.x = mState.scissor.x; - destScissoredRect.width -= xDiff; - sourceScissoredRect.x += xDiff; - sourceScissoredRect.width -= xDiff; - - } - - if (destRect.x + destRect.width > mState.scissor.x + mState.scissor.width) - { - int xDiff = (destRect.x + destRect.width) - (mState.scissor.x + mState.scissor.width); - destScissoredRect.width -= xDiff; - sourceScissoredRect.width -= xDiff; - } - - if (destRect.y < mState.scissor.y) + FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i); + if (attachment && attachment->isTexture()) { - int yDiff = mState.scissor.y - destRect.y; - destScissoredRect.y = mState.scissor.y; - destScissoredRect.height -= yDiff; - sourceScissoredRect.y += yDiff; - sourceScissoredRect.height -= yDiff; - } - - if (destRect.y + destRect.height > mState.scissor.y + mState.scissor.height) - { - int yDiff = (destRect.y + destRect.height) - (mState.scissor.y + mState.scissor.height); - destScissoredRect.height -= yDiff; - sourceScissoredRect.height -= yDiff; + (*outSerialArray)[serialCount++] = attachment->getTextureSerial(); } } - bool blitRenderTarget = false; - bool blitDepthStencil = false; - - Rectangle sourceTrimmedRect = sourceScissoredRect; - Rectangle destTrimmedRect = destScissoredRect; - - // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of - // the actual draw and read surfaces. - if (sourceTrimmedRect.x < 0) + FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer(); + if (depthStencilAttachment && depthStencilAttachment->isTexture()) { - int xDiff = 0 - sourceTrimmedRect.x; - sourceTrimmedRect.x = 0; - sourceTrimmedRect.width -= xDiff; - destTrimmedRect.x += xDiff; - destTrimmedRect.width -= xDiff; + (*outSerialArray)[serialCount++] = depthStencilAttachment->getTextureSerial(); } - if (sourceTrimmedRect.x + sourceTrimmedRect.width > readBufferWidth) - { - int xDiff = (sourceTrimmedRect.x + sourceTrimmedRect.width) - readBufferWidth; - sourceTrimmedRect.width -= xDiff; - destTrimmedRect.width -= xDiff; - } + std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount); - if (sourceTrimmedRect.y < 0) - { - int yDiff = 0 - sourceTrimmedRect.y; - sourceTrimmedRect.y = 0; - sourceTrimmedRect.height -= yDiff; - destTrimmedRect.y += yDiff; - destTrimmedRect.height -= yDiff; - } + return serialCount; +} - if (sourceTrimmedRect.y + sourceTrimmedRect.height > readBufferHeight) - { - int yDiff = (sourceTrimmedRect.y + sourceTrimmedRect.height) - readBufferHeight; - sourceTrimmedRect.height -= yDiff; - destTrimmedRect.height -= yDiff; - } +void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) +{ + Framebuffer *readFramebuffer = mState.getReadFramebuffer(); + Framebuffer *drawFramebuffer = mState.getDrawFramebuffer(); - if (destTrimmedRect.x < 0) + bool blitRenderTarget = false; + bool blitDepth = false; + bool blitStencil = false; + if ((mask & GL_COLOR_BUFFER_BIT) && readFramebuffer->getReadColorbuffer() && drawFramebuffer->getFirstColorbuffer()) { - int xDiff = 0 - destTrimmedRect.x; - destTrimmedRect.x = 0; - destTrimmedRect.width -= xDiff; - sourceTrimmedRect.x += xDiff; - sourceTrimmedRect.width -= xDiff; + blitRenderTarget = true; } - - if (destTrimmedRect.x + destTrimmedRect.width > drawBufferWidth) + if ((mask & GL_STENCIL_BUFFER_BIT) && readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer()) { - int xDiff = (destTrimmedRect.x + destTrimmedRect.width) - drawBufferWidth; - destTrimmedRect.width -= xDiff; - sourceTrimmedRect.width -= xDiff; + blitStencil = true; } - - if (destTrimmedRect.y < 0) + if ((mask & GL_DEPTH_BUFFER_BIT) && readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer()) { - int yDiff = 0 - destTrimmedRect.y; - destTrimmedRect.y = 0; - destTrimmedRect.height -= yDiff; - sourceTrimmedRect.y += yDiff; - sourceTrimmedRect.height -= yDiff; + blitDepth = true; } - if (destTrimmedRect.y + destTrimmedRect.height > drawBufferHeight) + gl::Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0); + gl::Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); + if (blitRenderTarget || blitDepth || blitStencil) { - int yDiff = (destTrimmedRect.y + destTrimmedRect.height) - drawBufferHeight; - destTrimmedRect.height -= yDiff; - sourceTrimmedRect.height -= yDiff; + const gl::Rectangle *scissor = mState.isScissorTestEnabled() ? &mState.getScissor() : NULL; + mRenderer->blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor, + blitRenderTarget, blitDepth, blitStencil, filter); } +} - bool partialBufferCopy = false; - if (sourceTrimmedRect.height < readBufferHeight || - sourceTrimmedRect.width < readBufferWidth || - destTrimmedRect.height < drawBufferHeight || - destTrimmedRect.width < drawBufferWidth || - sourceTrimmedRect.y != 0 || destTrimmedRect.y != 0 || sourceTrimmedRect.x != 0 || destTrimmedRect.x != 0) +void Context::invalidateFrameBuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, + GLint x, GLint y, GLsizei width, GLsizei height) +{ + Framebuffer *frameBuffer = NULL; + switch (target) { - partialBufferCopy = true; + case GL_FRAMEBUFFER: + case GL_DRAW_FRAMEBUFFER: + frameBuffer = mState.getDrawFramebuffer(); + break; + case GL_READ_FRAMEBUFFER: + frameBuffer = mState.getReadFramebuffer(); + break; + default: + UNREACHABLE(); } - if (mask & GL_COLOR_BUFFER_BIT) + if (frameBuffer && frameBuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) { - const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType(); - const bool validReadType = (readColorbufferType == GL_TEXTURE_2D) || (readColorbufferType == GL_RENDERBUFFER); - bool validDrawType = true; - bool validDrawFormat = true; - - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + for (int i = 0; i < numAttachments; ++i) { - if (drawFramebuffer->isEnabledColorAttachment(colorAttachment)) + 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 { - if (drawFramebuffer->getColorbufferType(colorAttachment) != GL_TEXTURE_2D && - drawFramebuffer->getColorbufferType(colorAttachment) != GL_RENDERBUFFER) + gl::FramebufferAttachment *attachment = NULL; + switch (attachments[i]) { - validDrawType = false; + 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 (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat()) + if (attachment) { - validDrawFormat = false; + renderTarget = attachment->getDepthStencil(); } } - } - if (!validReadType || !validDrawType || !validDrawFormat) - { - ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation"); - return gl::error(GL_INVALID_OPERATION); - } - - if (partialBufferCopy && readFramebuffer->getSamples() != 0) - { - return gl::error(GL_INVALID_OPERATION); + if (renderTarget) + { + renderTarget->invalidate(x, y, width, height); + } } - - blitRenderTarget = true; - } +} - if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) +bool Context::hasMappedBuffer(GLenum target) const +{ + if (target == GL_ARRAY_BUFFER) { - Renderbuffer *readDSBuffer = NULL; - Renderbuffer *drawDSBuffer = NULL; - - // We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have - // both a depth and stencil buffer, it will be the same buffer. - - if (mask & GL_DEPTH_BUFFER_BIT) + for (unsigned int attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; attribIndex++) { - if (readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer()) + const gl::VertexAttribute &vertexAttrib = mState.getVertexAttribState(attribIndex); + gl::Buffer *boundBuffer = vertexAttrib.buffer.get(); + if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped()) { - if (readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() || - readFramebuffer->getDepthbuffer()->getActualFormat() != drawFramebuffer->getDepthbuffer()->getActualFormat()) - { - return gl::error(GL_INVALID_OPERATION); - } - - blitDepthStencil = true; - readDSBuffer = readFramebuffer->getDepthbuffer(); - drawDSBuffer = drawFramebuffer->getDepthbuffer(); + 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; +} - if (mask & GL_STENCIL_BUFFER_BIT) - { - if (readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer()) - { - if (readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() || - readFramebuffer->getStencilbuffer()->getActualFormat() != drawFramebuffer->getStencilbuffer()->getActualFormat()) - { - return gl::error(GL_INVALID_OPERATION); - } +void Context::initCaps(GLuint clientVersion) +{ + mCaps = mRenderer->getRendererCaps(); - blitDepthStencil = true; - readDSBuffer = readFramebuffer->getStencilbuffer(); - drawDSBuffer = drawFramebuffer->getStencilbuffer(); - } - } + mExtensions = mRenderer->getRendererExtensions(); - if (partialBufferCopy) - { - ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); - return gl::error(GL_INVALID_OPERATION); // only whole-buffer copies are permitted - } + if (clientVersion < 3) + { + // Disable ES3+ extensions + mExtensions.colorBufferFloat = false; + } - if ((drawDSBuffer && drawDSBuffer->getSamples() != 0) || - (readDSBuffer && readDSBuffer->getSamples() != 0)) - { - return gl::error(GL_INVALID_OPERATION); - } + if (clientVersion > 2) + { + // FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts + //mExtensions.sRGB = false; } - if (blitRenderTarget || blitDepthStencil) + const TextureCapsMap &rendererFormats = mRenderer->getRendererTextureCaps(); + for (TextureCapsMap::const_iterator i = rendererFormats.begin(); i != rendererFormats.end(); i++) { - mRenderer->blitRect(readFramebuffer, sourceTrimmedRect, drawFramebuffer, destTrimmedRect, blitRenderTarget, blitDepthStencil); + GLenum format = i->first; + TextureCaps formatCaps = i->second; + + if (formatCaps.texturable && IsValidInternalFormat(format, mExtensions, clientVersion)) + { + // 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); + } } } @@ -2971,9 +2544,9 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 extern "C" { -gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) +gl::Context *glCreateContext(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) { - return new gl::Context(shareContext, renderer, notifyResets, robustAccess); + return new gl::Context(clientVersion, shareContext, renderer, notifyResets, robustAccess); } void glDestroyContext(gl::Context *context) diff --git a/src/3rdparty/angle/src/libGLESv2/Context.h b/src/3rdparty/angle/src/libGLESv2/Context.h index 3dc95e3b95..6c93c74e79 100644 --- a/src/3rdparty/angle/src/libGLESv2/Context.h +++ b/src/3rdparty/angle/src/libGLESv2/Context.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2013 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,26 +10,22 @@ #ifndef LIBGLESV2_CONTEXT_H_ #define LIBGLESV2_CONTEXT_H_ -#define GL_APICALL -#include -#include -#define EGLAPI -#include +#include "angle_gl.h" #include -#include #include -#ifdef _MSC_VER -#include -#else +#include #include -#endif +#include #include "common/angleutils.h" #include "common/RefCountObject.h" +#include "libGLESv2/Caps.h" #include "libGLESv2/HandleAllocator.h" #include "libGLESv2/angletypes.h" #include "libGLESv2/Constants.h" +#include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/State.h" namespace rx { @@ -49,6 +45,8 @@ class ProgramBinary; class Texture; class Texture2D; class TextureCubeMap; +class Texture3D; +class Texture2DArray; class Framebuffer; class Renderbuffer; class RenderbufferStorage; @@ -56,222 +54,28 @@ class Colorbuffer; class Depthbuffer; class Stencilbuffer; class DepthStencilbuffer; -class Fence; +class FenceNV; +class FenceSync; class Query; class ResourceManager; class Buffer; - -enum QueryType -{ - QUERY_ANY_SAMPLES_PASSED, - QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE, - - QUERY_TYPE_COUNT -}; - -// Helper structure describing a single vertex attribute -class VertexAttribute -{ - public: - VertexAttribute() : mType(GL_FLOAT), mSize(4), mNormalized(false), mStride(0), mPointer(NULL), mArrayEnabled(false), mDivisor(0) - { - mCurrentValue[0] = 0.0f; - mCurrentValue[1] = 0.0f; - mCurrentValue[2] = 0.0f; - mCurrentValue[3] = 1.0f; - } - - int typeSize() const - { - switch (mType) - { - case GL_BYTE: return mSize * sizeof(GLbyte); - case GL_UNSIGNED_BYTE: return mSize * sizeof(GLubyte); - case GL_SHORT: return mSize * sizeof(GLshort); - case GL_UNSIGNED_SHORT: return mSize * sizeof(GLushort); - case GL_FIXED: return mSize * sizeof(GLfixed); - case GL_FLOAT: return mSize * sizeof(GLfloat); - default: UNREACHABLE(); return mSize * sizeof(GLfloat); - } - } - - GLsizei stride() const - { - return mStride ? mStride : typeSize(); - } - - // From glVertexAttribPointer - GLenum mType; - GLint mSize; - bool mNormalized; - GLsizei mStride; // 0 means natural stride - - union - { - const void *mPointer; - intptr_t mOffset; - }; - - BindingPointer mBoundBuffer; // Captured when glVertexAttribPointer is called. - - bool mArrayEnabled; // From glEnable/DisableVertexAttribArray - float mCurrentValue[4]; // From glVertexAttrib - unsigned int mDivisor; -}; - -// Helper structure to store all raw state -struct State -{ - Color colorClearValue; - GLclampf depthClearValue; - int stencilClearValue; - - RasterizerState rasterizer; - bool scissorTest; - Rectangle scissor; - - BlendState blend; - Color blendColor; - bool sampleCoverage; - GLclampf sampleCoverageValue; - bool sampleCoverageInvert; - - DepthStencilState depthStencil; - GLint stencilRef; - GLint stencilBackRef; - - GLfloat lineWidth; - - GLenum generateMipmapHint; - GLenum fragmentShaderDerivativeHint; - - Rectangle viewport; - float zNear; - float zFar; - - unsigned int activeSampler; // Active texture unit selector - GL_TEXTURE0 - BindingPointer arrayBuffer; - BindingPointer elementArrayBuffer; - GLuint readFramebuffer; - GLuint drawFramebuffer; - BindingPointer renderbuffer; - GLuint currentProgram; - - VertexAttribute vertexAttribute[MAX_VERTEX_ATTRIBS]; - BindingPointer samplerTexture[TEXTURE_TYPE_COUNT][IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS]; - BindingPointer activeQuery[QUERY_TYPE_COUNT]; - - GLint unpackAlignment; - GLint packAlignment; - bool packReverseRowOrder; -}; +struct VertexAttribute; +class VertexArray; +class Sampler; +class TransformFeedback; class Context { public: - Context(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); + Context(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); - ~Context(); + virtual ~Context(); void makeCurrent(egl::Surface *surface); virtual void markContextLost(); bool isContextLost(); - // State manipulation - void setClearColor(float red, float green, float blue, float alpha); - - void setClearDepth(float depth); - - void setClearStencil(int stencil); - - void setCullFace(bool enabled); - bool isCullFaceEnabled() const; - - void setCullMode(GLenum mode); - - void setFrontFace(GLenum front); - - void setDepthTest(bool enabled); - bool isDepthTestEnabled() const; - - void setDepthFunc(GLenum depthFunc); - - void setDepthRange(float zNear, float zFar); - - void setBlend(bool enabled); - bool isBlendEnabled() const; - - void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha); - void setBlendColor(float red, float green, float blue, float alpha); - void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation); - - void setStencilTest(bool enabled); - bool isStencilTestEnabled() const; - - void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask); - void setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask); - void setStencilWritemask(GLuint stencilWritemask); - void setStencilBackWritemask(GLuint stencilBackWritemask); - void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass); - void setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass); - - void setPolygonOffsetFill(bool enabled); - bool isPolygonOffsetFillEnabled() const; - - void setPolygonOffsetParams(GLfloat factor, GLfloat units); - - void setSampleAlphaToCoverage(bool enabled); - bool isSampleAlphaToCoverageEnabled() const; - - void setSampleCoverage(bool enabled); - bool isSampleCoverageEnabled() const; - - void setSampleCoverageParams(GLclampf value, bool invert); - - void setScissorTest(bool enabled); - bool isScissorTestEnabled() const; - - void setDither(bool enabled); - bool isDitherEnabled() const; - - void setLineWidth(GLfloat width); - - void setGenerateMipmapHint(GLenum hint); - void setFragmentShaderDerivativeHint(GLenum hint); - - void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height); - - void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height); - - void setColorMask(bool red, bool green, bool blue, bool alpha); - void setDepthMask(bool mask); - - void setActiveSampler(unsigned int active); - - GLuint getReadFramebufferHandle() const; - GLuint getDrawFramebufferHandle() const; - GLuint getRenderbufferHandle() const; - - GLuint getArrayBufferHandle() const; - - GLuint getActiveQuery(GLenum target) const; - - void setEnableVertexAttribArray(unsigned int attribNum, bool enabled); - const VertexAttribute &getVertexAttribState(unsigned int attribNum); - void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, - bool normalized, GLsizei stride, const void *pointer); - const void *getVertexAttribPointer(unsigned int attribNum) const; - - void setUnpackAlignment(GLint alignment); - GLint getUnpackAlignment() const; - - void setPackAlignment(GLint alignment); - GLint getPackAlignment() const; - - void setPackReverseRowOrder(bool reverseRowOrder); - bool getPackReverseRowOrder() const; - // These create and destroy methods are merely pass-throughs to // ResourceManager, which owns these object types GLuint createBuffer(); @@ -279,35 +83,58 @@ class Context GLuint createProgram(); GLuint createTexture(); GLuint createRenderbuffer(); + GLuint createSampler(); + GLuint createTransformFeedback(); + GLsync createFenceSync(GLenum condition); void deleteBuffer(GLuint buffer); void deleteShader(GLuint shader); void deleteProgram(GLuint program); void deleteTexture(GLuint texture); void deleteRenderbuffer(GLuint renderbuffer); + void deleteSampler(GLuint sampler); + void deleteTransformFeedback(GLuint transformFeedback); + void deleteFenceSync(GLsync fenceSync); // Framebuffers are owned by the Context, so these methods do not pass through GLuint createFramebuffer(); void deleteFramebuffer(GLuint framebuffer); - // Fences are owned by the Context. - GLuint createFence(); - void deleteFence(GLuint fence); + // NV Fences are owned by the Context. + GLuint createFenceNV(); + void deleteFenceNV(GLuint fence); // Queries are owned by the Context; GLuint createQuery(); void deleteQuery(GLuint query); + // Vertex arrays are owned by the Context + GLuint createVertexArray(); + void deleteVertexArray(GLuint vertexArray); + void bindArrayBuffer(GLuint buffer); void bindElementArrayBuffer(GLuint buffer); void bindTexture2D(GLuint texture); void bindTextureCubeMap(GLuint texture); + void bindTexture3D(GLuint texture); + void bindTexture2DArray(GLuint texture); void bindReadFramebuffer(GLuint framebuffer); void bindDrawFramebuffer(GLuint framebuffer); void bindRenderbuffer(GLuint renderbuffer); + void bindVertexArray(GLuint vertexArray); + void bindSampler(GLuint textureUnit, GLuint sampler); + void bindGenericUniformBuffer(GLuint buffer); + void bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size); + void bindGenericTransformFeedbackBuffer(GLuint buffer); + void bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size); + void bindCopyReadBuffer(GLuint buffer); + void bindCopyWriteBuffer(GLuint buffer); + void bindPixelPackBuffer(GLuint buffer); + void bindPixelUnpackBuffer(GLuint buffer); void useProgram(GLuint program); void linkProgram(GLuint program); void setProgramBinary(GLuint program, const void *binary, GLint length); + void bindTransformFeedback(GLuint transformFeedback); void beginQuery(GLenum target, GLuint query); void endQuery(GLenum target); @@ -316,35 +143,54 @@ class Context void setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples); - void setVertexAttrib(GLuint index, const GLfloat *values); void setVertexAttribDivisor(GLuint index, GLuint divisor); + void samplerParameteri(GLuint sampler, GLenum pname, GLint param); + void samplerParameterf(GLuint sampler, GLenum pname, GLfloat param); + GLint getSamplerParameteri(GLuint sampler, GLenum pname); + GLfloat getSamplerParameterf(GLuint sampler, GLenum pname); + Buffer *getBuffer(GLuint handle); - Fence *getFence(GLuint handle); - Shader *getShader(GLuint handle); - Program *getProgram(GLuint handle); - Texture *getTexture(GLuint handle); - Framebuffer *getFramebuffer(GLuint handle); + FenceNV *getFenceNV(GLuint handle); + FenceSync *getFenceSync(GLsync handle) const; + Shader *getShader(GLuint handle) const; + Program *getProgram(GLuint handle) const; + Texture *getTexture(GLuint handle) const; + Framebuffer *getFramebuffer(GLuint handle) const; Renderbuffer *getRenderbuffer(GLuint handle); + VertexArray *getVertexArray(GLuint handle) const; + Sampler *getSampler(GLuint handle) const; Query *getQuery(GLuint handle, bool create, GLenum type); + TransformFeedback *getTransformFeedback(GLuint handle) const; + + Texture *getTargetTexture(GLenum target) const; + Texture2D *getTexture2D() const; + TextureCubeMap *getTextureCubeMap() const; + Texture3D *getTexture3D() const; + Texture2DArray *getTexture2DArray() const; + + Texture *getSamplerTexture(unsigned int sampler, TextureType type) const; + + bool isSampler(GLuint samplerName) const; - Buffer *getArrayBuffer(); - Buffer *getElementArrayBuffer(); - ProgramBinary *getCurrentProgramBinary(); - Texture2D *getTexture2D(); - TextureCubeMap *getTextureCubeMap(); - Texture *getSamplerTexture(unsigned int sampler, TextureType type); - Framebuffer *getReadFramebuffer(); - Framebuffer *getDrawFramebuffer(); + void getBooleanv(GLenum pname, GLboolean *params); + void getFloatv(GLenum pname, GLfloat *params); + void getIntegerv(GLenum pname, GLint *params); + void getInteger64v(GLenum pname, GLint64 *params); - bool getFloatv(GLenum pname, GLfloat *params); - bool getIntegerv(GLenum pname, GLint *params); - bool getBooleanv(GLenum pname, GLboolean *params); + bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data); + bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data); bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams); + bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams); - void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels); 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); void sync(bool block); // flush/finish @@ -359,101 +205,120 @@ class Context GLenum getResetStatus(); virtual bool isResetNotificationEnabled(); + virtual int getClientVersion() const; + + const Caps &getCaps() const; + const TextureCapsMap &getTextureCaps() const; + const Extensions &getExtensions() const; + int getMajorShaderModel() const; - float getMaximumPointSize() const; unsigned int getMaximumCombinedTextureImageUnits() const; - int getMaximumRenderbufferDimension() const; - int getMaximumTextureDimension() const; - int getMaximumCubeTextureDimension() const; - int getMaximumTextureLevel() const; - unsigned int getMaximumRenderTargets() const; + unsigned int getMaximumCombinedUniformBufferBindings() const; GLsizei getMaxSupportedSamples() const; - const char *getExtensionString() const; - const char *getRendererString() const; - bool supportsEventQueries() const; - bool supportsOcclusionQueries() const; - bool supportsBGRATextures() const; - bool supportsDXT1Textures() const; - bool supportsDXT3Textures() const; - bool supportsDXT5Textures() const; - bool supportsFloat32Textures() const; - bool supportsFloat32LinearFilter() const; - bool supportsFloat32RenderableTextures() const; - bool supportsFloat16Textures() const; - bool supportsFloat16LinearFilter() const; - bool supportsFloat16RenderableTextures() const; - bool supportsLuminanceTextures() const; - bool supportsLuminanceAlphaTextures() const; - bool supportsDepthTextures() const; - bool supports32bitIndices() const; - bool supportsNonPower2Texture() const; - bool supportsInstancing() const; - bool supportsTextureFilterAnisotropy() const; - - bool getCurrentReadFormatType(GLenum *format, GLenum *type); - - float getTextureMaxAnisotropy() const; - - void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, - GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask); + 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; + const std::string &getExtensionString(size_t idx) const; + size_t getExtensionStringCount() const; + + void getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type); + + 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; } + 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(); - void applyTextures(); - void applyTextures(SamplerType type); + 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(); + bool applyTransformFeedbackBuffers(); + void markTransformFeedbackUsage(); void detachBuffer(GLuint buffer); void detachTexture(GLuint texture); void detachFramebuffer(GLuint framebuffer); void detachRenderbuffer(GLuint renderbuffer); + void detachVertexArray(GLuint vertexArray); + void detachTransformFeedback(GLuint transformFeedback); + void detachSampler(GLuint sampler); + void generateSwizzles(Texture *textures[], size_t count); + size_t getCurrentTexturesAndSamplerStates(ProgramBinary *programBinary, SamplerType type, Texture **outTextures, + TextureType *outTextureTypes, SamplerState *outSamplers); Texture *getIncompleteTexture(TextureType type); bool skipDraw(GLenum drawMode); - void initExtensionString(); void initRendererString(); + void initExtensionStrings(); - typedef std::set FramebufferTextureSerialSet; - FramebufferTextureSerialSet getBoundFramebufferTextureSerials(); + size_t getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray); - rx::Renderer *const mRenderer; + void initCaps(GLuint clientVersion); + // Caps to use for validation + Caps mCaps; + TextureCapsMap mTextureCaps; + Extensions mExtensions; + + rx::Renderer *const mRenderer; State mState; + int mClientVersion; + BindingPointer mTexture2DZero; BindingPointer mTextureCubeMapZero; + BindingPointer mTexture3DZero; + BindingPointer mTexture2DArrayZero; -#ifndef HASH_MAP -# ifdef _MSC_VER -# define HASH_MAP stdext::hash_map -# else -# define HASH_MAP std::unordered_map -# endif -#endif - - typedef HASH_MAP FramebufferMap; + typedef std::unordered_map FramebufferMap; FramebufferMap mFramebufferMap; HandleAllocator mFramebufferHandleAllocator; - typedef HASH_MAP FenceMap; - FenceMap mFenceMap; - HandleAllocator mFenceHandleAllocator; + typedef std::unordered_map FenceNVMap; + FenceNVMap mFenceNVMap; + HandleAllocator mFenceNVHandleAllocator; - typedef HASH_MAP QueryMap; + typedef std::unordered_map QueryMap; QueryMap mQueryMap; HandleAllocator mQueryHandleAllocator; - const char *mExtensionString; - const char *mRendererString; - + typedef std::unordered_map VertexArrayMap; + VertexArrayMap mVertexArrayMap; + HandleAllocator mVertexArrayHandleAllocator; + + BindingPointer mTransformFeedbackZero; + typedef std::unordered_map TransformFeedbackMap; + TransformFeedbackMap mTransformFeedbackMap; + HandleAllocator mTransformFeedbackAllocator; + + std::string mRendererString; + std::string mExtensionString; + std::vector mExtensionStrings; + BindingPointer mIncompleteTextures[TEXTURE_TYPE_COUNT]; // Recorded errors @@ -470,37 +335,8 @@ class Context GLenum mResetStrategy; bool mRobustAccess; - BindingPointer mCurrentProgramBinary; - Framebuffer *mBoundDrawFramebuffer; - int mMajorShaderModel; - float mMaximumPointSize; bool mSupportsVertexTexture; - bool mSupportsNonPower2Texture; - bool mSupportsInstancing; - int mMaxViewportDimension; - int mMaxRenderbufferDimension; - int mMaxTextureDimension; - int mMaxCubeTextureDimension; - int mMaxTextureLevel; - float mMaxTextureAnisotropy; - bool mSupportsEventQueries; - bool mSupportsOcclusionQueries; - bool mSupportsBGRATextures; - bool mSupportsDXT1Textures; - bool mSupportsDXT3Textures; - bool mSupportsDXT5Textures; - bool mSupportsFloat32Textures; - bool mSupportsFloat32LinearFilter; - bool mSupportsFloat32RenderableTextures; - bool mSupportsFloat16Textures; - bool mSupportsFloat16LinearFilter; - bool mSupportsFloat16RenderableTextures; - bool mSupportsLuminanceTextures; - bool mSupportsLuminanceAlphaTextures; - bool mSupportsDepthTextures; - bool mSupports32bitIndices; - bool mSupportsTextureFilterAnisotropy; int mNumCompressedTextureFormats; ResourceManager *mResourceManager; diff --git a/src/3rdparty/angle/src/libGLESv2/DynamicHLSL.cpp b/src/3rdparty/angle/src/libGLESv2/DynamicHLSL.cpp new file mode 100644 index 0000000000..e3ec391bfa --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/DynamicHLSL.cpp @@ -0,0 +1,1122 @@ +// +// 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 new file mode 100644 index 0000000000..68abd6e1a4 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/DynamicHLSL.h @@ -0,0 +1,96 @@ +// +// 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/Fence.cpp b/src/3rdparty/angle/src/libGLESv2/Fence.cpp index e4218bbeec..31d149d629 100644 --- a/src/3rdparty/angle/src/libGLESv2/Fence.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Fence.cpp @@ -7,46 +7,187 @@ // Fence.cpp: Implements the gl::Fence class, which supports the GL_NV_fence extension. +// Important note on accurate timers in Windows: +// +// QueryPerformanceCounter has a few major issues, including being 10x as expensive to call +// as timeGetTime on laptops and "jumping" during certain hardware events. +// +// See the comments at the top of the Chromium source file "chromium/src/base/time/time_win.cc" +// https://code.google.com/p/chromium/codesearch#chromium/src/base/time/time_win.cc +// +// We still opt to use QPC. In the present and moving forward, most newer systems will not suffer +// from buggy implementations. + #include "libGLESv2/Fence.h" #include "libGLESv2/renderer/FenceImpl.h" #include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/main.h" namespace gl { -Fence::Fence(rx::Renderer *renderer) +FenceNV::FenceNV(rx::Renderer *renderer) { mFence = renderer->createFence(); } -Fence::~Fence() +FenceNV::~FenceNV() { delete mFence; } -GLboolean Fence::isFence() +GLboolean FenceNV::isFence() const +{ + // GL_NV_fence spec: + // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. + return (mFence->isSet() ? GL_TRUE : GL_FALSE); +} + +void FenceNV::setFence(GLenum condition) +{ + mFence->set(); + + mCondition = condition; + mStatus = GL_FALSE; +} + +GLboolean FenceNV::testFence() +{ + // Flush the command buffer by default + bool result = mFence->test(true); + + mStatus = (result ? GL_TRUE : GL_FALSE); + return mStatus; +} + +void FenceNV::finishFence() +{ + ASSERT(mFence->isSet()); + + while (!mFence->test(true)) + { + Sleep(0); + } +} + +GLint FenceNV::getFencei(GLenum pname) +{ + ASSERT(mFence->isSet()); + + switch (pname) + { + case GL_FENCE_STATUS_NV: + { + // GL_NV_fence spec: + // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV + // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. + if (mStatus == GL_TRUE) + { + return GL_TRUE; + } + + mStatus = (mFence->test(false) ? GL_TRUE : GL_FALSE); + return mStatus; + } + + case GL_FENCE_CONDITION_NV: + return mCondition; + + default: UNREACHABLE(); return 0; + } +} + +FenceSync::FenceSync(rx::Renderer *renderer, GLuint id) + : RefCountObject(id) { - return mFence->isFence(); + mFence = renderer->createFence(); + + LARGE_INTEGER counterFreqency = { 0 }; + BOOL success = QueryPerformanceFrequency(&counterFreqency); + UNUSED_ASSERTION_VARIABLE(success); + ASSERT(success); + + mCounterFrequency = counterFreqency.QuadPart; +} + +FenceSync::~FenceSync() +{ + delete mFence; } -void Fence::setFence(GLenum condition) +void FenceSync::set(GLenum condition) { - mFence->setFence(condition); + mCondition = condition; + mFence->set(); } -GLboolean Fence::testFence() +GLenum FenceSync::clientWait(GLbitfield flags, GLuint64 timeout) { - return mFence->testFence(); + ASSERT(mFence->isSet()); + + bool flushCommandBuffer = ((flags & GL_SYNC_FLUSH_COMMANDS_BIT) != 0); + + if (mFence->test(flushCommandBuffer)) + { + return GL_ALREADY_SIGNALED; + } + + if (mFence->hasError()) + { + return GL_WAIT_FAILED; + } + + if (timeout == 0) + { + return GL_TIMEOUT_EXPIRED; + } + + LARGE_INTEGER currentCounter = { 0 }; + BOOL success = QueryPerformanceCounter(¤tCounter); + UNUSED_ASSERTION_VARIABLE(success); + ASSERT(success); + + LONGLONG timeoutInSeconds = static_cast(timeout) * static_cast(1000000ll); + LONGLONG endCounter = currentCounter.QuadPart + mCounterFrequency * timeoutInSeconds; + + while (currentCounter.QuadPart < endCounter && !mFence->test(flushCommandBuffer)) + { + Sleep(0); + BOOL success = QueryPerformanceCounter(¤tCounter); + UNUSED_ASSERTION_VARIABLE(success); + ASSERT(success); + } + + if (mFence->hasError()) + { + return GL_WAIT_FAILED; + } + + if (currentCounter.QuadPart >= endCounter) + { + return GL_TIMEOUT_EXPIRED; + } + + return GL_CONDITION_SATISFIED; } -void Fence::finishFence() +void FenceSync::serverWait() { - mFence->finishFence(); + // Because our API is currently designed to be called from a single thread, we don't need to do + // extra work for a server-side fence. GPU commands issued after the fence is created will always + // be processed after the fence is signaled. } -void Fence::getFenceiv(GLenum pname, GLint *params) +GLenum FenceSync::getStatus() const { - mFence->getFenceiv(pname, params); + if (mFence->test(false)) + { + // The spec does not specify any way to report errors during the status test (e.g. device lost) + // so we report the fence is unblocked in case of error or signaled. + return GL_SIGNALED; + } + + return GL_UNSIGNALED; } } diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.h b/src/3rdparty/angle/src/libGLESv2/Fence.h index 1cedebb112..291edb3de1 100644 --- a/src/3rdparty/angle/src/libGLESv2/Fence.h +++ b/src/3rdparty/angle/src/libGLESv2/Fence.h @@ -10,6 +10,7 @@ #define LIBGLESV2_FENCE_H_ #include "common/angleutils.h" +#include "common/RefCountObject.h" namespace rx { @@ -20,22 +21,50 @@ class FenceImpl; namespace gl { -class Fence +class FenceNV { public: - explicit Fence(rx::Renderer *renderer); - virtual ~Fence(); + explicit FenceNV(rx::Renderer *renderer); + virtual ~FenceNV(); - GLboolean isFence(); + GLboolean isFence() const; void setFence(GLenum condition); GLboolean testFence(); void finishFence(); - void getFenceiv(GLenum pname, GLint *params); + GLint getFencei(GLenum pname); + + GLboolean getStatus() const { return mStatus; } + GLuint getCondition() const { return mCondition; } private: - DISALLOW_COPY_AND_ASSIGN(Fence); + DISALLOW_COPY_AND_ASSIGN(FenceNV); rx::FenceImpl *mFence; + + GLboolean mStatus; + GLenum mCondition; +}; + +class FenceSync : public RefCountObject +{ + public: + explicit FenceSync(rx::Renderer *renderer, GLuint id); + virtual ~FenceSync(); + + void set(GLenum condition); + GLenum clientWait(GLbitfield flags, GLuint64 timeout); + void serverWait(); + GLenum getStatus() const; + + GLuint getCondition() const { return mCondition; } + + private: + DISALLOW_COPY_AND_ASSIGN(FenceSync); + + rx::FenceImpl *mFence; + LONGLONG mCounterFrequency; + + GLenum mCondition; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp index b0abba0ac4..f808175250 100644 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" // -// Copyright (c) 2002-2013 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,253 +11,288 @@ #include "libGLESv2/Framebuffer.h" #include "libGLESv2/main.h" -#include "libGLESv2/utilities.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" namespace gl { -Framebuffer::Framebuffer(rx::Renderer *renderer) - : mRenderer(renderer) +Framebuffer::Framebuffer(rx::Renderer *renderer, GLuint id) + : mRenderer(renderer), + mId(id), + mReadBufferState(GL_COLOR_ATTACHMENT0_EXT), + mDepthbuffer(NULL), + mStencilbuffer(NULL) { for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - mColorbufferTypes[colorAttachment] = GL_NONE; + mColorbuffers[colorAttachment] = NULL; mDrawBufferStates[colorAttachment] = GL_NONE; } mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT; - mReadBufferState = GL_COLOR_ATTACHMENT0_EXT; - - mDepthbufferType = GL_NONE; - mStencilbufferType = GL_NONE; } Framebuffer::~Framebuffer() { for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - mColorbufferPointers[colorAttachment].set(NULL); + SafeDelete(mColorbuffers[colorAttachment]); } - mDepthbufferPointer.set(NULL); - mStencilbufferPointer.set(NULL); + SafeDelete(mDepthbuffer); + SafeDelete(mStencilbuffer); } -Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const +FramebufferAttachment *Framebuffer::createAttachment(GLenum type, GLuint handle, GLint level, GLint layer) const { - gl::Context *context = gl::getContext(); - Renderbuffer *buffer = NULL; - - if (type == GL_NONE) + if (handle == 0) { - buffer = NULL; + return NULL; } - else if (type == GL_RENDERBUFFER) - { - buffer = context->getRenderbuffer(handle); - } - else if (IsInternalTextureTarget(type)) - { - buffer = context->getTexture(handle)->getRenderbuffer(type); - } - else + + gl::Context *context = gl::getContext(); + + switch (type) { + case GL_NONE: + return NULL; + + case GL_RENDERBUFFER: + return new RenderbufferAttachment(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); + } + else + { + return NULL; + } + } + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + { + Texture *texture = context->getTexture(handle); + if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP) + { + TextureCubeMap *texCube = static_cast(texture); + return new TextureCubeMapAttachment(texCube, type, level); + } + else + { + return NULL; + } + } + + case GL_TEXTURE_3D: + { + Texture *texture = context->getTexture(handle); + if (texture && texture->getTarget() == GL_TEXTURE_3D) + { + Texture3D *tex3D = static_cast(texture); + return new Texture3DAttachment(tex3D, level, layer); + } + else + { + return NULL; + } + } + + case GL_TEXTURE_2D_ARRAY: + { + Texture *texture = context->getTexture(handle); + if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY) + { + Texture2DArray *tex2DArray = static_cast(texture); + return new Texture2DArrayAttachment(tex2DArray, level, layer); + } + else + { + return NULL; + } + } + + default: UNREACHABLE(); + return NULL; } - - return buffer; } -void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer) +void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer) { ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); - mColorbufferTypes[colorAttachment] = (colorbuffer != 0) ? type : GL_NONE; - mColorbufferPointers[colorAttachment].set(lookupRenderbuffer(type, colorbuffer)); + SafeDelete(mColorbuffers[colorAttachment]); + mColorbuffers[colorAttachment] = createAttachment(type, colorbuffer, level, layer); } -void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer) +void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer) { - mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE; - mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer)); + SafeDelete(mDepthbuffer); + mDepthbuffer = createAttachment(type, depthbuffer, level, layer); } -void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer) +void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer) { - mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE; - mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer)); + SafeDelete(mStencilbuffer); + mStencilbuffer = createAttachment(type, stencilbuffer, level, layer); } -void Framebuffer::detachTexture(GLuint texture) +void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer) { - for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - if (mColorbufferPointers[colorAttachment].id() == texture && IsInternalTextureTarget(mColorbufferTypes[colorAttachment])) - { - mColorbufferTypes[colorAttachment] = GL_NONE; - mColorbufferPointers[colorAttachment].set(NULL); - } - } + FramebufferAttachment *attachment = createAttachment(type, depthStencilBuffer, level, layer); - if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType)) - { - mDepthbufferType = GL_NONE; - mDepthbufferPointer.set(NULL); - } + SafeDelete(mDepthbuffer); + SafeDelete(mStencilbuffer); - if (mStencilbufferPointer.id() == texture && IsInternalTextureTarget(mStencilbufferType)) + // ensure this is a legitimate depth+stencil format + if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0) { - mStencilbufferType = GL_NONE; - mStencilbufferPointer.set(NULL); + mDepthbuffer = attachment; + + // Make a new attachment object to ensure we do not double-delete + // See angle issue 686 + mStencilbuffer = createAttachment(type, depthStencilBuffer, level, layer); } } -void Framebuffer::detachRenderbuffer(GLuint renderbuffer) +void Framebuffer::detachTexture(GLuint textureId) { for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - if (mColorbufferPointers[colorAttachment].id() == renderbuffer && mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER) + FramebufferAttachment *attachment = mColorbuffers[colorAttachment]; + + if (attachment && attachment->isTextureWithId(textureId)) { - mColorbufferTypes[colorAttachment] = GL_NONE; - mColorbufferPointers[colorAttachment].set(NULL); + SafeDelete(mColorbuffers[colorAttachment]); } } - if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER) + if (mDepthbuffer && mDepthbuffer->isTextureWithId(textureId)) { - mDepthbufferType = GL_NONE; - mDepthbufferPointer.set(NULL); + SafeDelete(mDepthbuffer); } - if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER) + if (mStencilbuffer && mStencilbuffer->isTextureWithId(textureId)) { - mStencilbufferType = GL_NONE; - mStencilbufferPointer.set(NULL); + SafeDelete(mStencilbuffer); } } -unsigned int Framebuffer::getRenderTargetSerial(unsigned int colorAttachment) const +void Framebuffer::detachRenderbuffer(GLuint renderbufferId) { - ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); + for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + FramebufferAttachment *attachment = mColorbuffers[colorAttachment]; - Renderbuffer *colorbuffer = mColorbufferPointers[colorAttachment].get(); + if (attachment && attachment->isRenderbufferWithId(renderbufferId)) + { + SafeDelete(mColorbuffers[colorAttachment]); + } + } - if (colorbuffer) + if (mDepthbuffer && mDepthbuffer->isRenderbufferWithId(renderbufferId)) { - return colorbuffer->getSerial(); + SafeDelete(mDepthbuffer); } - return 0; -} - -unsigned int Framebuffer::getDepthbufferSerial() const -{ - Renderbuffer *depthbuffer = mDepthbufferPointer.get(); - - if (depthbuffer) + if (mStencilbuffer && mStencilbuffer->isRenderbufferWithId(renderbufferId)) { - return depthbuffer->getSerial(); + SafeDelete(mStencilbuffer); } - - return 0; } -unsigned int Framebuffer::getStencilbufferSerial() const +FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const { - Renderbuffer *stencilbuffer = mStencilbufferPointer.get(); - - if (stencilbuffer) - { - return stencilbuffer->getSerial(); - } - - return 0; + ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); + return mColorbuffers[colorAttachment]; } -Renderbuffer *Framebuffer::getColorbuffer(unsigned int colorAttachment) const +FramebufferAttachment *Framebuffer::getDepthbuffer() const { - ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); - return mColorbufferPointers[colorAttachment].get(); + return mDepthbuffer; } -Renderbuffer *Framebuffer::getDepthbuffer() const +FramebufferAttachment *Framebuffer::getStencilbuffer() const { - return mDepthbufferPointer.get(); + return mStencilbuffer; } -Renderbuffer *Framebuffer::getStencilbuffer() const +FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const { - return mStencilbufferPointer.get(); + return (hasValidDepthStencil() ? mDepthbuffer : NULL); } -Renderbuffer *Framebuffer::getDepthOrStencilbuffer() const +FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const { - Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get(); + FramebufferAttachment *depthstencilbuffer = mDepthbuffer; if (!depthstencilbuffer) { - depthstencilbuffer = mStencilbufferPointer.get(); + depthstencilbuffer = mStencilbuffer; } return depthstencilbuffer; } -Renderbuffer *Framebuffer::getReadColorbuffer() const +FramebufferAttachment *Framebuffer::getReadColorbuffer() const { // Will require more logic if glReadBuffers is supported - return mColorbufferPointers[0].get(); + return mColorbuffers[0]; } GLenum Framebuffer::getReadColorbufferType() const { // Will require more logic if glReadBuffers is supported - return mColorbufferTypes[0]; + return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE); } -Renderbuffer *Framebuffer::getFirstColorbuffer() const +FramebufferAttachment *Framebuffer::getFirstColorbuffer() const { for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - if (mColorbufferTypes[colorAttachment] != GL_NONE) + if (mColorbuffers[colorAttachment]) { - return mColorbufferPointers[colorAttachment].get(); + return mColorbuffers[colorAttachment]; } } return NULL; } -GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const +FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const { - ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); - return mColorbufferTypes[colorAttachment]; -} - -GLenum Framebuffer::getDepthbufferType() const -{ - return mDepthbufferType; -} - -GLenum Framebuffer::getStencilbufferType() const -{ - return mStencilbufferType; -} - -GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const -{ - ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); - return mColorbufferPointers[colorAttachment].id(); -} - -GLuint Framebuffer::getDepthbufferHandle() const -{ - return mDepthbufferPointer.id(); -} - -GLuint Framebuffer::getStencilbufferHandle() const -{ - return mStencilbufferPointer.id(); + if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15) + { + return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0); + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: + return getDepthbuffer(); + case GL_STENCIL_ATTACHMENT: + return getStencilbuffer(); + case GL_DEPTH_STENCIL_ATTACHMENT: + return getDepthStencilBuffer(); + default: + UNREACHABLE(); + return NULL; + } + } } GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const @@ -272,7 +307,7 @@ void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBu bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const { - return (mColorbufferTypes[colorAttachment] != GL_NONE && mDrawBufferStates[colorAttachment] != GL_NONE); + return (mColorbuffers[colorAttachment] && mDrawBufferStates[colorAttachment] != GL_NONE); } bool Framebuffer::hasEnabledColorAttachment() const @@ -290,17 +325,7 @@ bool Framebuffer::hasEnabledColorAttachment() const bool Framebuffer::hasStencil() const { - if (mStencilbufferType != GL_NONE) - { - const Renderbuffer *stencilbufferObject = getStencilbuffer(); - - if (stencilbufferObject) - { - return stencilbufferObject->getStencilSize() > 0; - } - } - - return false; + return (mStencilbuffer && mStencilbuffer->getStencilSize() > 0); } bool Framebuffer::usingExtendedDrawBuffers() const @@ -320,63 +345,43 @@ GLenum Framebuffer::completeness() const { int width = 0; int height = 0; - int colorbufferSize = 0; + unsigned int colorbufferSize = 0; int samples = -1; bool missingAttachment = true; + GLuint clientVersion = mRenderer->getCurrentClientVersion(); for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - if (mColorbufferTypes[colorAttachment] != GL_NONE) - { - const Renderbuffer *colorbuffer = getColorbuffer(colorAttachment); - - if (!colorbuffer) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } + const FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment]; + if (colorbuffer) + { if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - if (mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER) + GLenum internalformat = colorbuffer->getInternalFormat(); + // TODO(geofflang): use context's texture caps + const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + if (colorbuffer->isTexture()) { - if (!gl::IsColorRenderable(colorbuffer->getInternalFormat())) - { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } - } - else if (IsInternalTextureTarget(mColorbufferTypes[colorAttachment])) - { - GLint internalformat = colorbuffer->getInternalFormat(); - GLenum format = gl::ExtractFormat(internalformat); - - if (IsCompressed(format) || - format == GL_ALPHA || - format == GL_LUMINANCE || - format == GL_LUMINANCE_ALPHA) + if (!formatCaps.renderable) { return GL_FRAMEBUFFER_UNSUPPORTED; } - bool filtering, renderable; - - if ((gl::IsFloat32Format(internalformat) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) || - (gl::IsFloat16Format(internalformat) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable))) - { - return GL_FRAMEBUFFER_UNSUPPORTED; - } - - if (gl::IsDepthTexture(internalformat) || gl::IsStencilTexture(internalformat)) + if (gl::GetDepthBits(internalformat) > 0 || gl::GetStencilBits(internalformat) > 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else { - UNREACHABLE(); - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + if (!formatCaps.renderable || gl::GetDepthBits(internalformat) > 0 || gl::GetStencilBits(internalformat) > 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } } if (!missingAttachment) @@ -394,16 +399,24 @@ GLenum Framebuffer::completeness() const return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT; } - // all color attachments attachments must have the same number of bitplanes - if (gl::ComputePixelSize(colorbuffer->getInternalFormat()) != colorbufferSize) + // in GLES 2.0, all color attachments attachments must have the same number of bitplanes + // in GLES 3.0, there is no such restriction + if (clientVersion < 3) { - return GL_FRAMEBUFFER_UNSUPPORTED; + if (gl::GetPixelBytes(colorbuffer->getInternalFormat()) != colorbufferSize) + { + return GL_FRAMEBUFFER_UNSUPPORTED; + } } // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++) { - if (mColorbufferPointers[colorAttachment].get() == mColorbufferPointers[previousColorAttachment].get()) + const FramebufferAttachment *previousAttachment = mColorbuffers[previousColorAttachment]; + + if (previousAttachment && + (colorbuffer->id() == previousAttachment->id() && + colorbuffer->type() == previousAttachment->type())) { return GL_FRAMEBUFFER_UNSUPPORTED; } @@ -414,129 +427,120 @@ GLenum Framebuffer::completeness() const width = colorbuffer->getWidth(); height = colorbuffer->getHeight(); samples = colorbuffer->getSamples(); - colorbufferSize = gl::ComputePixelSize(colorbuffer->getInternalFormat()); + colorbufferSize = gl::GetPixelBytes(colorbuffer->getInternalFormat()); missingAttachment = false; } } } - const Renderbuffer *depthbuffer = NULL; - const Renderbuffer *stencilbuffer = NULL; - - if (mDepthbufferType != GL_NONE) + if (mDepthbuffer) { - depthbuffer = getDepthbuffer(); - - if (!depthbuffer) + if (mDepthbuffer->getWidth() == 0 || mDepthbuffer->getHeight() == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0) + GLenum internalformat = mDepthbuffer->getInternalFormat(); + // TODO(geofflang): use context's texture caps + const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + if (mDepthbuffer->isTexture()) { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } + GLenum internalformat = mDepthbuffer->getInternalFormat(); - if (mDepthbufferType == GL_RENDERBUFFER) - { - if (!gl::IsDepthRenderable(depthbuffer->getInternalFormat())) + // depth texture attachments require OES/ANGLE_depth_texture + // TODO(geofflang): use context's extensions + if (!mRenderer->getRendererExtensions().depthTextures) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - } - else if (IsInternalTextureTarget(mDepthbufferType)) - { - GLint internalformat = depthbuffer->getInternalFormat(); - // depth texture attachments require OES/ANGLE_depth_texture - if (!mRenderer->getDepthTextureSupport()) + if (!formatCaps.renderable) { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + return GL_FRAMEBUFFER_UNSUPPORTED; } - if (!gl::IsDepthTexture(internalformat)) + if (gl::GetDepthBits(internalformat) == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else { - UNREACHABLE(); - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + if (!formatCaps.renderable || gl::GetDepthBits(internalformat) == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } } if (missingAttachment) { - width = depthbuffer->getWidth(); - height = depthbuffer->getHeight(); - samples = depthbuffer->getSamples(); + width = mDepthbuffer->getWidth(); + height = mDepthbuffer->getHeight(); + samples = mDepthbuffer->getSamples(); missingAttachment = false; } - else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight()) + else if (width != mDepthbuffer->getWidth() || height != mDepthbuffer->getHeight()) { return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; } - else if (samples != depthbuffer->getSamples()) + else if (samples != mDepthbuffer->getSamples()) { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; } } - if (mStencilbufferType != GL_NONE) + if (mStencilbuffer) { - stencilbuffer = getStencilbuffer(); - - if (!stencilbuffer) + if (mStencilbuffer->getWidth() == 0 || mStencilbuffer->getHeight() == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0) + GLenum internalformat = mStencilbuffer->getInternalFormat(); + // TODO(geofflang): use context's texture caps + const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat); + if (mStencilbuffer->isTexture()) { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; - } + GLenum internalformat = mStencilbuffer->getInternalFormat(); - if (mStencilbufferType == GL_RENDERBUFFER) - { - if (!gl::IsStencilRenderable(stencilbuffer->getInternalFormat())) + // texture stencil attachments come along as part + // of OES_packed_depth_stencil + OES/ANGLE_depth_texture + // TODO(geofflang): use context's extensions + if (!mRenderer->getRendererExtensions().depthTextures) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } - } - else if (IsInternalTextureTarget(mStencilbufferType)) - { - GLint internalformat = stencilbuffer->getInternalFormat(); - // texture stencil attachments come along as part - // of OES_packed_depth_stencil + OES/ANGLE_depth_texture - if (!mRenderer->getDepthTextureSupport()) + if (!formatCaps.renderable) { - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + return GL_FRAMEBUFFER_UNSUPPORTED; } - if (!gl::IsStencilTexture(internalformat)) + if (gl::GetStencilBits(internalformat) == 0) { return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; } } else { - UNREACHABLE(); - return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + if (!formatCaps.renderable || gl::GetStencilBits(internalformat) == 0) + { + return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; + } } if (missingAttachment) { - width = stencilbuffer->getWidth(); - height = stencilbuffer->getHeight(); - samples = stencilbuffer->getSamples(); + width = mStencilbuffer->getWidth(); + height = mStencilbuffer->getHeight(); + samples = mStencilbuffer->getSamples(); missingAttachment = false; } - else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight()) + else if (width != mStencilbuffer->getWidth() || height != mStencilbuffer->getHeight()) { return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; } - else if (samples != stencilbuffer->getSamples()) + else if (samples != mStencilbuffer->getSamples()) { return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; } @@ -544,7 +548,7 @@ GLenum Framebuffer::completeness() const // if we have both a depth and stencil buffer, they must refer to the same object // since we only support packed_depth_stencil and not separate depth and stencil - if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer)) + if (mDepthbuffer && mStencilbuffer && !hasValidDepthStencil()) { return GL_FRAMEBUFFER_UNSUPPORTED; } @@ -559,17 +563,17 @@ GLenum Framebuffer::completeness() const } DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) - : Framebuffer(renderer) + : Framebuffer(renderer, 0) { - mColorbufferPointers[0].set(new Renderbuffer(mRenderer, 0, colorbuffer)); + Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer); + mColorbuffers[0] = new RenderbufferAttachment(colorRenderbuffer); - Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil); - mDepthbufferPointer.set(depthStencilRenderbuffer); - mStencilbufferPointer.set(depthStencilRenderbuffer); + Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil); - mColorbufferTypes[0] = GL_RENDERBUFFER; - mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE; - mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE; + // 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); mDrawBufferStates[0] = GL_BACK; mReadBufferState = GL_BACK; @@ -583,9 +587,9 @@ int Framebuffer::getSamples() const // in this case return the first nonzero sample size for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) { - if (mColorbufferTypes[colorAttachment] != GL_NONE) + if (mColorbuffers[colorAttachment]) { - return getColorbuffer(colorAttachment)->getSamples(); + return mColorbuffers[colorAttachment]->getSamples(); } } } @@ -593,6 +597,15 @@ int Framebuffer::getSamples() const return 0; } +bool Framebuffer::hasValidDepthStencil() const +{ + // A valid depth-stencil attachment has the same resource bound to both the + // depth and stencil attachment points. + return (mDepthbuffer && mStencilbuffer && + mDepthbuffer->type() == mStencilbuffer->type() && + mDepthbuffer->id() == mStencilbuffer->id()); +} + GLenum DefaultFramebuffer::completeness() const { // The default framebuffer *must* always be complete, though it may not be @@ -600,4 +613,22 @@ GLenum DefaultFramebuffer::completeness() const return GL_FRAMEBUFFER_COMPLETE; } +FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) const +{ + switch (attachment) + { + case GL_BACK: + return getColorbuffer(0); + case GL_DEPTH: + return getDepthbuffer(); + case GL_STENCIL: + return getStencilbuffer(); + case GL_DEPTH_STENCIL: + return getDepthStencilBuffer(); + default: + UNREACHABLE(); + return NULL; + } +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h index 50bfd4fd0f..035e16fa45 100644 --- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h @@ -12,7 +12,7 @@ #include "common/angleutils.h" #include "common/RefCountObject.h" -#include "Constants.h" +#include "constants.h" namespace rx { @@ -21,7 +21,7 @@ class Renderer; namespace gl { -class Renderbuffer; +class FramebufferAttachment; class Colorbuffer; class Depthbuffer; class Stencilbuffer; @@ -30,36 +30,30 @@ class DepthStencilbuffer; class Framebuffer { public: - explicit Framebuffer(rx::Renderer *renderer); + Framebuffer(rx::Renderer *renderer, GLuint id); virtual ~Framebuffer(); - void setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer); - void setDepthbuffer(GLenum type, GLuint depthbuffer); - void setStencilbuffer(GLenum type, GLuint stencilbuffer); + GLuint id() const { return mId; } + + void setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer); + void setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer); + void setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer); + void setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer); void detachTexture(GLuint texture); void detachRenderbuffer(GLuint renderbuffer); - unsigned int getRenderTargetSerial(unsigned int colorAttachment) const; - unsigned int getDepthbufferSerial() const; - unsigned int getStencilbufferSerial() const; - - Renderbuffer *getColorbuffer(unsigned int colorAttachment) const; - Renderbuffer *getDepthbuffer() const; - Renderbuffer *getStencilbuffer() const; - Renderbuffer *getDepthOrStencilbuffer() const; - Renderbuffer *getReadColorbuffer() const; + FramebufferAttachment *getColorbuffer(unsigned int colorAttachment) const; + FramebufferAttachment *getDepthbuffer() const; + FramebufferAttachment *getStencilbuffer() const; + FramebufferAttachment *getDepthStencilBuffer() const; + FramebufferAttachment *getDepthOrStencilbuffer() const; + FramebufferAttachment *getReadColorbuffer() const; GLenum getReadColorbufferType() const; - Renderbuffer *getFirstColorbuffer() const; - - GLenum getColorbufferType(unsigned int colorAttachment) const; - GLenum getDepthbufferType() const; - GLenum getStencilbufferType() const; + FramebufferAttachment *getFirstColorbuffer() const; - GLuint getColorbufferHandle(unsigned int colorAttachment) const; - GLuint getDepthbufferHandle() const; - GLuint getStencilbufferHandle() const; + virtual FramebufferAttachment *getAttachment(GLenum attachment) const; GLenum getDrawBufferState(unsigned int colorAttachment) const; void setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer); @@ -71,25 +65,24 @@ class Framebuffer bool usingExtendedDrawBuffers() const; virtual GLenum completeness() const; + bool hasValidDepthStencil() const; protected: - GLenum mColorbufferTypes[IMPLEMENTATION_MAX_DRAW_BUFFERS]; - BindingPointer mColorbufferPointers[IMPLEMENTATION_MAX_DRAW_BUFFERS]; - GLenum mDrawBufferStates[IMPLEMENTATION_MAX_DRAW_BUFFERS]; - GLenum mReadBufferState; + rx::Renderer *mRenderer; - GLenum mDepthbufferType; - BindingPointer mDepthbufferPointer; + GLuint mId; - GLenum mStencilbufferType; - BindingPointer mStencilbufferPointer; + FramebufferAttachment *mColorbuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS]; + GLenum mDrawBufferStates[IMPLEMENTATION_MAX_DRAW_BUFFERS]; + GLenum mReadBufferState; - rx::Renderer *mRenderer; + FramebufferAttachment *mDepthbuffer; + FramebufferAttachment *mStencilbuffer; - private: +private: DISALLOW_COPY_AND_ASSIGN(Framebuffer); - Renderbuffer *lookupRenderbuffer(GLenum type, GLuint handle) const; + FramebufferAttachment *createAttachment(GLenum type, GLuint handle, GLint level, GLint layer) const; }; class DefaultFramebuffer : public Framebuffer @@ -98,6 +91,7 @@ class DefaultFramebuffer : public Framebuffer DefaultFramebuffer(rx::Renderer *Renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil); virtual GLenum completeness() const; + virtual FramebufferAttachment *getAttachment(GLenum attachment) const; private: DISALLOW_COPY_AND_ASSIGN(DefaultFramebuffer); diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp new file mode 100644 index 0000000000..5855301c97 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp @@ -0,0 +1,495 @@ +#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 +// found in the LICENSE file. +// + +// FramebufferAttachment.cpp: the gl::FramebufferAttachment class and its derived classes +// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. + +#include "libGLESv2/FramebufferAttachment.h" +#include "libGLESv2/renderer/RenderTarget.h" + +#include "libGLESv2/Texture.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() +{ +} + +GLuint FramebufferAttachment::getRedSize() const +{ + return (gl::GetRedBits(getInternalFormat()) > 0) ? gl::GetRedBits(getActualFormat()) : 0; +} + +GLuint FramebufferAttachment::getGreenSize() const +{ + return (gl::GetGreenBits(getInternalFormat()) > 0) ? gl::GetGreenBits(getActualFormat()) : 0; +} + +GLuint FramebufferAttachment::getBlueSize() const +{ + return (gl::GetBlueBits(getInternalFormat()) > 0) ? gl::GetBlueBits(getActualFormat()) : 0; +} + +GLuint FramebufferAttachment::getAlphaSize() const +{ + return (gl::GetAlphaBits(getInternalFormat()) > 0) ? gl::GetAlphaBits(getActualFormat()) : 0; +} + +GLuint FramebufferAttachment::getDepthSize() const +{ + return (gl::GetDepthBits(getInternalFormat()) > 0) ? gl::GetDepthBits(getActualFormat()) : 0; +} + +GLuint FramebufferAttachment::getStencilSize() const +{ + return (gl::GetStencilBits(getInternalFormat()) > 0) ? gl::GetStencilBits(getActualFormat()) : 0; +} + +GLenum FramebufferAttachment::getComponentType() const +{ + return gl::GetComponentType(getActualFormat()); +} + +GLenum FramebufferAttachment::getColorEncoding() const +{ + return gl::GetColorEncoding(getActualFormat()); +} + +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); +} + +GLenum Texture3DAttachment::getInternalFormat() const +{ + return mTexture3D->getInternalFormat(mLevel); +} + +GLenum Texture3DAttachment::getActualFormat() const +{ + return mTexture3D->getActualFormat(mLevel); +} + +GLsizei Texture3DAttachment::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() +{ + return mTexture2DArray->getRenderTarget(mLevel, mLayer); +} + +rx::RenderTarget *Texture2DArrayAttachment::getDepthStencil() +{ + return mTexture2DArray->getDepthStencil(mLevel, mLayer); +} + +rx::TextureStorage *Texture2DArrayAttachment::getTextureStorage() +{ + return mTexture2DArray->getNativeTexture()->getStorageInstance(); +} + +GLsizei Texture2DArrayAttachment::getWidth() const +{ + return mTexture2DArray->getWidth(mLevel); +} + +GLsizei Texture2DArrayAttachment::getHeight() const +{ + return mTexture2DArray->getHeight(mLevel); +} + +GLenum Texture2DArrayAttachment::getInternalFormat() const +{ + return mTexture2DArray->getInternalFormat(mLevel); +} + +GLenum Texture2DArrayAttachment::getActualFormat() const +{ + return mTexture2DArray->getActualFormat(mLevel); +} + +GLsizei Texture2DArrayAttachment::getSamples() 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; +} + +GLint Texture2DArrayAttachment::mipLevel() const +{ + return mLevel; +} + +GLint Texture2DArrayAttachment::layer() const +{ + return mLayer; +} + +unsigned int Texture2DArrayAttachment::getTextureSerial() const +{ + return mTexture2DArray->getTextureSerial(); +} + +////// RenderbufferAttachment Implementation ////// + +RenderbufferAttachment::RenderbufferAttachment(Renderbuffer *renderbuffer) +{ + ASSERT(renderbuffer); + mRenderbuffer.set(renderbuffer); +} + +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(); +} + +GLsizei RenderbufferAttachment::getHeight() const +{ + return mRenderbuffer->getHeight(); +} + +GLenum RenderbufferAttachment::getInternalFormat() const +{ + return mRenderbuffer->getInternalFormat(); +} + +GLenum RenderbufferAttachment::getActualFormat() const +{ + return mRenderbuffer->getActualFormat(); +} + +GLsizei RenderbufferAttachment::getSamples() const +{ + return mRenderbuffer->getStorage()->getSamples(); +} + +unsigned int RenderbufferAttachment::getSerial() const +{ + return mRenderbuffer->getStorage()->getSerial(); +} + +GLuint RenderbufferAttachment::id() const +{ + return mRenderbuffer->id(); +} + +GLenum RenderbufferAttachment::type() const +{ + return GL_RENDERBUFFER; +} + +GLint RenderbufferAttachment::mipLevel() const +{ + return 0; +} + +GLint RenderbufferAttachment::layer() const +{ + return 0; +} + +unsigned int RenderbufferAttachment::getTextureSerial() const +{ + UNREACHABLE(); + return 0; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h new file mode 100644 index 0000000000..18768f9831 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h @@ -0,0 +1,246 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// FramebufferAttachment.h: Defines the wrapper class gl::FramebufferAttachment, as well as the +// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108. + +#ifndef LIBGLESV2_FRAMEBUFFERATTACHMENT_H_ +#define LIBGLESV2_FRAMEBUFFERATTACHMENT_H_ + +#include "angle_gl.h" + +#include "common/angleutils.h" +#include "common/RefCountObject.h" + +namespace rx +{ +class Renderer; +class RenderTarget; +class TextureStorage; +} + +namespace gl +{ +class Texture2D; +class TextureCubeMap; +class Texture3D; +class Texture2DArray; +class Renderbuffer; + +// FramebufferAttachment implements a GL framebuffer attachment. +// Attachments are "light" containers, which store pointers to ref-counted GL objects. +// We support GL texture (2D/3D/Cube/2D array) and renderbuffer object attachments. +// Note: Our old naming scheme used the term "Renderbuffer" for both GL renderbuffers and for +// framebuffer attachments, which confused their usage. + +class FramebufferAttachment +{ + public: + FramebufferAttachment(); + virtual ~FramebufferAttachment(); + + // Helper methods + GLuint getRedSize() const; + GLuint getGreenSize() const; + GLuint getBlueSize() const; + GLuint getAlphaSize() const; + GLuint getDepthSize() const; + GLuint getStencilSize() const; + GLenum getComponentType() const; + GLenum getColorEncoding() const; + bool isTexture() const; + + bool isTextureWithId(GLuint textureId) const { return isTexture() && id() == textureId; } + bool isRenderbufferWithId(GLuint renderbufferId) const { return !isTexture() && id() == renderbufferId; } + + // Child class interface + virtual rx::RenderTarget *getRenderTarget() = 0; + virtual rx::RenderTarget *getDepthStencil() = 0; + virtual rx::TextureStorage *getTextureStorage() = 0; + + virtual GLsizei getWidth() const = 0; + virtual GLsizei getHeight() const = 0; + virtual GLenum getInternalFormat() const = 0; + virtual GLenum getActualFormat() const = 0; + virtual GLsizei getSamples() const = 0; + + 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; + + private: + DISALLOW_COPY_AND_ASSIGN(Texture2DAttachment); + + BindingPointer mTexture2D; + const GLint mLevel; +}; + +class TextureCubeMapAttachment : public FramebufferAttachment +{ + public: + TextureCubeMapAttachment(TextureCubeMap *texture, GLenum faceTarget, GLint level); + + 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; + + private: + DISALLOW_COPY_AND_ASSIGN(Texture2DArrayAttachment); + + BindingPointer mTexture2DArray; + const GLint mLevel; + const GLint mLayer; +}; + +class RenderbufferAttachment : public FramebufferAttachment +{ + public: + RenderbufferAttachment(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; + + private: + DISALLOW_COPY_AND_ASSIGN(RenderbufferAttachment); + + BindingPointer mRenderbuffer; +}; + +} + +#endif // LIBGLESV2_FRAMEBUFFERATTACHMENT_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h index a92e1684d4..bbded02f99 100644 --- a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h +++ b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h @@ -10,8 +10,7 @@ #ifndef LIBGLESV2_HANDLEALLOCATOR_H_ #define LIBGLESV2_HANDLEALLOCATOR_H_ -#define GL_APICALL -#include +#include "angle_gl.h" #include diff --git a/src/3rdparty/angle/src/libGLESv2/Program.cpp b/src/3rdparty/angle/src/libGLESv2/Program.cpp index c38aa5a61a..8a9fb04800 100644 --- a/src/3rdparty/angle/src/libGLESv2/Program.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Program.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" // -// Copyright (c) 2002-2013 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. // @@ -95,32 +95,36 @@ void InfoLog::append(const char *format, ...) return; } - char info[1024]; - va_list vararg; va_start(vararg, format); - vsnprintf(info, sizeof(info), format, vararg); + size_t infoLength = vsnprintf(NULL, 0, format, vararg); va_end(vararg); - size_t infoLength = strlen(info); + char *logPointer = NULL; if (!mInfoLog) { mInfoLog = new char[infoLength + 2]; - strcpy(mInfoLog, info); - strcpy(mInfoLog + infoLength, "\n"); + logPointer = mInfoLog; } else { - size_t logLength = strlen(mInfoLog); - char *newLog = new char[logLength + infoLength + 2]; + size_t currentlogLength = strlen(mInfoLog); + char *newLog = new char[currentlogLength + infoLength + 2]; strcpy(newLog, mInfoLog); - strcpy(newLog + logLength, info); - strcpy(newLog + logLength + infoLength, "\n"); delete[] mInfoLog; mInfoLog = newLog; + + logPointer = mInfoLog + currentlogLength; } + + va_start(vararg, format); + vsnprintf(logPointer, infoLength, format, vararg); + va_end(vararg); + + logPointer[infoLength] = 0; + strcpy(logPointer + infoLength, "\n"); } void InfoLog::reset() @@ -141,6 +145,8 @@ Program::Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle mLinked = false; mRefCount = 0; mRenderer = renderer; + + resetUniformBlockBindings(); } Program::~Program() @@ -243,9 +249,11 @@ bool Program::link() unlink(false); mInfoLog.reset(); + resetUniformBlockBindings(); mProgramBinary.set(new ProgramBinary(mRenderer)); - mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader); + mLinked = mProgramBinary->link(mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader, + mTransformFeedbackVaryings, mTransformFeedbackBufferMode); return mLinked; } @@ -290,7 +298,7 @@ bool Program::isLinked() return mLinked; } -ProgramBinary* Program::getProgramBinary() +ProgramBinary* Program::getProgramBinary() const { return mProgramBinary.get(); } @@ -522,4 +530,132 @@ bool Program::isValidated() const } } +GLint Program::getActiveUniformBlockCount() +{ + ProgramBinary *programBinary = getProgramBinary(); + if (programBinary) + { + return static_cast(programBinary->getActiveUniformBlockCount()); + } + else + { + return 0; + } +} + +GLint Program::getActiveUniformBlockMaxLength() +{ + ProgramBinary *programBinary = getProgramBinary(); + if (programBinary) + { + return static_cast(programBinary->getActiveUniformBlockMaxLength()); + } + else + { + return 0; + } +} + +void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding) +{ + mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding; +} + +GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const +{ + return mUniformBlockBindings[uniformBlockIndex]; +} + +void Program::resetUniformBlockBindings() +{ + for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++) + { + mUniformBlockBindings[blockId] = 0; + } +} + +void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode) +{ + mTransformFeedbackVaryings.resize(count); + for (GLsizei i = 0; i < count; i++) + { + mTransformFeedbackVaryings[i] = varyings[i]; + } + + mTransformFeedbackBufferMode = bufferMode; +} + +void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const +{ + ProgramBinary *programBinary = getProgramBinary(); + if (programBinary && index < programBinary->getTransformFeedbackVaryingCount()) + { + const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(index); + GLsizei lastNameIdx = std::min(bufSize - 1, static_cast(varying.name.length())); + if (length) + { + *length = lastNameIdx; + } + if (size) + { + *size = varying.size; + } + if (type) + { + *type = varying.type; + } + if (name) + { + memcpy(name, varying.name.c_str(), lastNameIdx); + name[lastNameIdx] = '\0'; + } + } +} + +GLsizei Program::getTransformFeedbackVaryingCount() const +{ + ProgramBinary *programBinary = getProgramBinary(); + if (programBinary) + { + return static_cast(programBinary->getTransformFeedbackVaryingCount()); + } + else + { + return 0; + } +} + +GLsizei Program::getTransformFeedbackVaryingMaxLength() const +{ + ProgramBinary *programBinary = getProgramBinary(); + if (programBinary) + { + GLsizei maxSize = 0; + for (size_t i = 0; i < programBinary->getTransformFeedbackVaryingCount(); i++) + { + const LinkedVarying &varying = programBinary->getTransformFeedbackVarying(i); + maxSize = std::max(maxSize, static_cast(varying.name.length() + 1)); + } + + return maxSize; + } + else + { + return 0; + } +} + +GLenum Program::getTransformFeedbackBufferMode() const +{ + ProgramBinary *programBinary = getProgramBinary(); + if (programBinary) + { + return programBinary->getTransformFeedbackBufferMode(); + } + else + { + return mTransformFeedbackBufferMode; + } +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/Program.h b/src/3rdparty/angle/src/libGLESv2/Program.h index a9db83403d..ce821a470b 100644 --- a/src/3rdparty/angle/src/libGLESv2/Program.h +++ b/src/3rdparty/angle/src/libGLESv2/Program.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. // @@ -16,6 +16,7 @@ #include "common/angleutils.h" #include "common/RefCountObject.h" #include "libGLESv2/Constants.h" +#include "libGLESv2/ProgramBinary.h" namespace rx { @@ -27,7 +28,6 @@ namespace gl class ResourceManager; class FragmentShader; class VertexShader; -class ProgramBinary; class Shader; extern const char * const g_fakepath; @@ -78,7 +78,7 @@ class Program bool link(); bool isLinked(); bool setProgramBinary(const void *binary, GLsizei length); - ProgramBinary *getProgramBinary(); + ProgramBinary *getProgramBinary() const; int getInfoLogLength() const; void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog); @@ -92,6 +92,18 @@ class Program GLint getActiveUniformCount(); GLint getActiveUniformMaxLength(); + GLint getActiveUniformBlockCount(); + GLint getActiveUniformBlockMaxLength(); + + void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding); + GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const; + + void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode); + void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const; + GLsizei getTransformFeedbackVaryingCount() const; + GLsizei getTransformFeedbackVaryingMaxLength() const; + GLenum getTransformFeedbackBufferMode() const; + void addRef(); void release(); unsigned int getRefCount() const; @@ -107,12 +119,18 @@ class Program DISALLOW_COPY_AND_ASSIGN(Program); void unlink(bool destroy = false); + void resetUniformBlockBindings(); FragmentShader *mFragmentShader; VertexShader *mVertexShader; AttributeBindings mAttributeBindings; + GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS]; + + std::vector mTransformFeedbackVaryings; + GLuint mTransformFeedbackBufferMode; + BindingPointer mProgramBinary; bool mLinked; bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp index 13c515a594..9fad5fbfc5 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" // -// Copyright (c) 2002-2013 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,50 +10,182 @@ #include "libGLESv2/BinaryStream.h" #include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" #include "libGLESv2/renderer/ShaderExecutable.h" #include "common/debug.h" #include "common/version.h" -#include "utilities.h" +#include "common/utilities.h" #include "libGLESv2/main.h" #include "libGLESv2/Shader.h" #include "libGLESv2/Program.h" #include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/VertexDataManager.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 { -std::string str(int i) + +namespace +{ + +TextureType GetTextureType(GLenum samplerType) +{ + switch (samplerType) + { + case GL_SAMPLER_2D: + case GL_INT_SAMPLER_2D: + case GL_UNSIGNED_INT_SAMPLER_2D: + case GL_SAMPLER_2D_SHADOW: + return TEXTURE_2D; + case GL_SAMPLER_3D: + case GL_INT_SAMPLER_3D: + case GL_UNSIGNED_INT_SAMPLER_3D: + return TEXTURE_3D; + case GL_SAMPLER_CUBE: + case GL_SAMPLER_CUBE_SHADOW: + return TEXTURE_CUBE; + case GL_INT_SAMPLER_CUBE: + case GL_UNSIGNED_INT_SAMPLER_CUBE: + return TEXTURE_CUBE; + 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; + default: UNREACHABLE(); + } + + return TEXTURE_2D; +} + +unsigned int ParseAndStripArrayIndex(std::string* name) { - char buffer[20]; - snprintf(buffer, sizeof(buffer), "%d", i); - return buffer; + unsigned int subscript = GL_INVALID_INDEX; + + // Strip any trailing array operator and retrieve the subscript + size_t open = name->find_last_of('['); + size_t close = name->find_last_of(']'); + if (open != std::string::npos && close == name->length() - 1) + { + subscript = atoi(name->substr(open + 1).c_str()); + name->erase(open); + } + + return subscript; } -static rx::D3DWorkaroundType DiscardWorkaround(bool usesDiscard) +void GetInputLayoutFromShader(const std::vector &shaderAttributes, VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) { - return (usesDiscard ? rx::ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER : rx::ANGLE_D3D_WORKAROUND_NONE); + size_t layoutIndex = 0; + for (size_t attributeIndex = 0; attributeIndex < shaderAttributes.size(); attributeIndex++) + { + ASSERT(layoutIndex < MAX_VERTEX_ATTRIBS); + + const sh::Attribute &shaderAttr = shaderAttributes[attributeIndex]; + + if (shaderAttr.type != GL_NONE) + { + GLenum transposedType = TransposeMatrixType(shaderAttr.type); + + for (size_t rowIndex = 0; static_cast(rowIndex) < VariableRowCount(transposedType); rowIndex++, layoutIndex++) + { + VertexFormat *defaultFormat = &inputLayout[layoutIndex]; + + defaultFormat->mType = VariableComponentType(transposedType); + defaultFormat->mNormalized = false; + defaultFormat->mPureInteger = (defaultFormat->mType != GL_FLOAT); // note: inputs can not be bool + defaultFormat->mComponents = VariableColumnCount(transposedType); + } + } + } +} + } -UniformLocation::UniformLocation(const std::string &name, unsigned int element, unsigned int index) +VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index) : name(name), element(element), index(index) { } -unsigned int ProgramBinary::mCurrentSerial = 1; +ProgramBinary::VertexExecutable::VertexExecutable(const VertexFormat inputLayout[], + const GLenum signature[], + rx::ShaderExecutable *shaderExecutable) + : mShaderExecutable(shaderExecutable) +{ + for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + { + mInputs[attributeIndex] = inputLayout[attributeIndex]; + mSignature[attributeIndex] = signature[attributeIndex]; + } +} -ProgramBinary::ProgramBinary(rx::Renderer *renderer) : mRenderer(renderer), RefCountObject(0), mSerial(issueSerial()) +ProgramBinary::VertexExecutable::~VertexExecutable() { - mPixelExecutable = NULL; - mVertexExecutable = NULL; - mGeometryExecutable = NULL; + SafeDelete(mShaderExecutable); +} - mValidated = false; +bool ProgramBinary::VertexExecutable::matchesSignature(const GLenum signature[]) const +{ + for (size_t attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + { + if (mSignature[attributeIndex] != signature[attributeIndex]) + { + return false; + } + } + + return true; +} + +ProgramBinary::PixelExecutable::PixelExecutable(const std::vector &outputSignature, rx::ShaderExecutable *shaderExecutable) + : mOutputSignature(outputSignature), + mShaderExecutable(shaderExecutable) +{ +} + +ProgramBinary::PixelExecutable::~PixelExecutable() +{ + SafeDelete(mShaderExecutable); +} + +LinkedVarying::LinkedVarying() +{ +} + +LinkedVarying::LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName, + unsigned int semanticIndex, unsigned int semanticIndexCount) + : name(name), type(type), size(size), semanticName(semanticName), semanticIndex(semanticIndex), semanticIndexCount(semanticIndexCount) +{ +} + +unsigned int ProgramBinary::mCurrentSerial = 1; +ProgramBinary::ProgramBinary(rx::Renderer *renderer) + : RefCountObject(0), + mRenderer(renderer), + mDynamicHLSL(NULL), + mVertexWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE), + mPixelWorkarounds(rx::ANGLE_D3D_WORKAROUND_NONE), + mGeometryExecutable(NULL), + mUsedVertexSamplerRange(0), + mUsedPixelSamplerRange(0), + mUsesPointSize(false), + mShaderVersion(100), + mDirtySamplerMapping(true), + mVertexUniformStorage(NULL), + mFragmentUniformStorage(NULL), + mValidated(false), + mSerial(issueSerial()) +{ for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++) { mSemanticIndex[index] = -1; @@ -69,27 +201,13 @@ ProgramBinary::ProgramBinary(rx::Renderer *renderer) : mRenderer(renderer), RefC mSamplersVS[index].active = false; } - mUsedVertexSamplerRange = 0; - mUsedPixelSamplerRange = 0; - mUsesPointSize = false; + mDynamicHLSL = new DynamicHLSL(renderer); } ProgramBinary::~ProgramBinary() { - delete mPixelExecutable; - mPixelExecutable = NULL; - - delete mVertexExecutable; - mVertexExecutable = NULL; - - delete mGeometryExecutable; - mGeometryExecutable = NULL; - - while (!mUniforms.empty()) - { - delete mUniforms.back(); - mUniforms.pop_back(); - } + reset(); + SafeDelete(mDynamicHLSL); } unsigned int ProgramBinary::getSerial() const @@ -97,22 +215,108 @@ unsigned int ProgramBinary::getSerial() const return mSerial; } +int ProgramBinary::getShaderVersion() const +{ + return mShaderVersion; +} + unsigned int ProgramBinary::issueSerial() { return mCurrentSerial++; } -rx::ShaderExecutable *ProgramBinary::getPixelExecutable() +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++) + { + if (fbo->getColorbuffer(outputIndex) != NULL) + { + // Always output floats for now + outputs[outputIndex] = GL_FLOAT; + } + else + { + outputs[outputIndex] = GL_NONE; + } + } + + return getPixelExecutableForOutputLayout(outputs); +} + +rx::ShaderExecutable *ProgramBinary::getPixelExecutableForOutputLayout(const std::vector &outputSignature) { - return mPixelExecutable; + for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++) + { + if (mPixelExecutables[executableIndex]->matchesSignature(outputSignature)) + { + return mPixelExecutables[executableIndex]->shaderExecutable(); + } + } + + 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); + + if (!pixelExecutable) + { + std::vector tempCharBuffer(tempInfoLog.getLength() + 3); + tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]); + ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]); + } + else + { + mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable)); + } + + return pixelExecutable; } -rx::ShaderExecutable *ProgramBinary::getVertexExecutable() +rx::ShaderExecutable *ProgramBinary::getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]) { - return mVertexExecutable; + GLenum signature[MAX_VERTEX_ATTRIBS]; + mDynamicHLSL->getInputLayoutSignature(inputLayout, signature); + + for (size_t executableIndex = 0; executableIndex < mVertexExecutables.size(); executableIndex++) + { + if (mVertexExecutables[executableIndex]->matchesSignature(signature)) + { + return mVertexExecutables[executableIndex]->shaderExecutable(); + } + } + + // 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); + + if (!vertexExecutable) + { + std::vector tempCharBuffer(tempInfoLog.getLength()+3); + tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]); + ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]); + } + else + { + mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable)); + } + + return vertexExecutable; } -rx::ShaderExecutable *ProgramBinary::getGeometryExecutable() +rx::ShaderExecutable *ProgramBinary::getGeometryExecutable() const { return mGeometryExecutable; } @@ -136,7 +340,7 @@ GLuint ProgramBinary::getAttributeLocation(const char *name) int ProgramBinary::getSemanticIndex(int attributeIndex) { ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS); - + return mSemanticIndex[attributeIndex]; } @@ -179,7 +383,7 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd switch (type) { case SAMPLER_PIXEL: - ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0])); + ASSERT(samplerIndex < ArraySize(mSamplersPS)); if (mSamplersPS[samplerIndex].active) { @@ -187,7 +391,7 @@ GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerInd } break; case SAMPLER_VERTEX: - ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0])); + ASSERT(samplerIndex < ArraySize(mSamplersVS)); if (mSamplersVS[samplerIndex].active) { @@ -212,11 +416,11 @@ TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int switch (type) { case SAMPLER_PIXEL: - ASSERT(samplerIndex < sizeof(mSamplersPS)/sizeof(mSamplersPS[0])); + ASSERT(samplerIndex < ArraySize(mSamplersPS)); ASSERT(mSamplersPS[samplerIndex].active); return mSamplersPS[samplerIndex].textureType; case SAMPLER_VERTEX: - ASSERT(samplerIndex < sizeof(mSamplersVS)/sizeof(mSamplersVS[0])); + ASSERT(samplerIndex < ArraySize(mSamplersVS)); ASSERT(mSamplersVS[samplerIndex].active); return mSamplersVS[samplerIndex].textureType; default: UNREACHABLE(); @@ -227,402 +431,352 @@ TextureType ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int GLint ProgramBinary::getUniformLocation(std::string name) { - unsigned int subscript = 0; - - // Strip any trailing array operator and retrieve the subscript - size_t open = name.find_last_of('['); - size_t close = name.find_last_of(']'); - if (open != std::string::npos && close == name.length() - 1) - { - subscript = atoi(name.substr(open + 1).c_str()); - name.erase(open); - } + unsigned int subscript = ParseAndStripArrayIndex(&name); unsigned int numUniforms = mUniformIndex.size(); for (unsigned int location = 0; location < numUniforms; location++) { - if (mUniformIndex[location].name == name && - mUniformIndex[location].element == subscript) + if (mUniformIndex[location].name == name) { - return location; + const int index = mUniformIndex[location].index; + const bool isArray = mUniforms[index]->isArray(); + + if ((isArray && mUniformIndex[location].element == subscript) || + (subscript == GL_INVALID_INDEX)) + { + return location; + } } } return -1; } -bool ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v) +GLuint ProgramBinary::getUniformIndex(std::string name) { - if (location < 0 || location >= (int)mUniformIndex.size()) - { - return false; - } - - Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; - targetUniform->dirty = true; - - int elementCount = targetUniform->elementCount(); - - if (elementCount == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(elementCount - (int)mUniformIndex[location].element, count); + unsigned int subscript = ParseAndStripArrayIndex(&name); - if (targetUniform->type == GL_FLOAT) + // The app is not allowed to specify array indices other than 0 for arrays of basic types + if (subscript != 0 && subscript != GL_INVALID_INDEX) { - GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - target[0] = v[0]; - target[1] = 0; - target[2] = 0; - target[3] = 0; - target += 4; - v += 1; - } + return GL_INVALID_INDEX; } - else if (targetUniform->type == GL_BOOL) - { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - for (int i = 0; i < count; i++) + unsigned int numUniforms = mUniforms.size(); + for (unsigned int index = 0; index < numUniforms; index++) + { + if (mUniforms[index]->name == name) { - boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE; - boolParams[1] = GL_FALSE; - boolParams[2] = GL_FALSE; - boolParams[3] = GL_FALSE; - boolParams += 4; - v += 1; + if (mUniforms[index]->isArray() || subscript == GL_INVALID_INDEX) + { + return index; + } } } - else - { - return false; - } - return true; + return GL_INVALID_INDEX; } -bool ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) +GLuint ProgramBinary::getUniformBlockIndex(std::string name) { - if (location < 0 || location >= (int)mUniformIndex.size()) + unsigned int subscript = ParseAndStripArrayIndex(&name); + + unsigned int numUniformBlocks = mUniformBlocks.size(); + for (unsigned int blockIndex = 0; blockIndex < numUniformBlocks; blockIndex++) { - return false; + const UniformBlock &uniformBlock = *mUniformBlocks[blockIndex]; + if (uniformBlock.name == name) + { + const bool arrayElementZero = (subscript == GL_INVALID_INDEX && uniformBlock.elementIndex == 0); + if (subscript == uniformBlock.elementIndex || arrayElementZero) + { + return blockIndex; + } + } } - Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; - targetUniform->dirty = true; - - int elementCount = targetUniform->elementCount(); + return GL_INVALID_INDEX; +} - if (elementCount == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION +UniformBlock *ProgramBinary::getUniformBlockByIndex(GLuint blockIndex) +{ + ASSERT(blockIndex < mUniformBlocks.size()); + return mUniformBlocks[blockIndex]; +} - count = std::min(elementCount - (int)mUniformIndex[location].element, count); +GLint ProgramBinary::getFragDataLocation(const char *name) const +{ + std::string baseName(name); + unsigned int arrayIndex; + arrayIndex = ParseAndStripArrayIndex(&baseName); - if (targetUniform->type == GL_FLOAT_VEC2) + for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++) { - GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; + const VariableLocation &outputVariable = locationIt->second; - for (int i = 0; i < count; i++) + if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element)) { - target[0] = v[0]; - target[1] = v[1]; - target[2] = 0; - target[3] = 0; - target += 4; - v += 2; + return static_cast(locationIt->first); } } - else if (targetUniform->type == GL_BOOL_VEC2) - { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - for (int i = 0; i < count; i++) - { - boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE; - boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE; - boolParams[2] = GL_FALSE; - boolParams[3] = GL_FALSE; - boolParams += 4; - v += 2; - } - } - else - { - return false; - } + return -1; +} - return true; +size_t ProgramBinary::getTransformFeedbackVaryingCount() const +{ + return mTransformFeedbackLinkedVaryings.size(); } -bool ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) +const LinkedVarying &ProgramBinary::getTransformFeedbackVarying(size_t idx) const { - if (location < 0 || location >= (int)mUniformIndex.size()) - { - return false; - } + return mTransformFeedbackLinkedVaryings[idx]; +} - Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; - targetUniform->dirty = true; +GLenum ProgramBinary::getTransformFeedbackBufferMode() const +{ + return mTransformFeedbackBufferMode; +} - int elementCount = targetUniform->elementCount(); +template +static inline void SetIfDirty(T *dest, const T& source, bool *dirtyFlag) +{ + ASSERT(dest != NULL); + ASSERT(dirtyFlag != NULL); - if (elementCount == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION + *dirtyFlag = *dirtyFlag || (memcmp(dest, &source, sizeof(T)) != 0); + *dest = source; +} + +template +void ProgramBinary::setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType) +{ + const int components = VariableComponentCount(targetUniformType); + const GLenum targetBoolType = VariableBoolVectorType(targetUniformType); + + LinkedUniform *targetUniform = getUniformByLocation(location); + + int elementCount = targetUniform->elementCount(); count = std::min(elementCount - (int)mUniformIndex[location].element, count); - if (targetUniform->type == GL_FLOAT_VEC3) + if (targetUniform->type == targetUniformType) { - GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; + T *target = (T*)targetUniform->data + mUniformIndex[location].element * 4; for (int i = 0; i < count; i++) { - target[0] = v[0]; - target[1] = v[1]; - target[2] = v[2]; - target[3] = 0; + for (int c = 0; c < components; c++) + { + SetIfDirty(target + c, v[c], &targetUniform->dirty); + } + for (int c = components; c < 4; c++) + { + SetIfDirty(target + c, T(0), &targetUniform->dirty); + } target += 4; - v += 3; + v += components; } } - else if (targetUniform->type == GL_BOOL_VEC3) + else if (targetUniform->type == targetBoolType) { GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; for (int i = 0; i < count; i++) { - boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE; - boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE; - boolParams[2] = (v[2] == 0.0f) ? GL_FALSE : GL_TRUE; - boolParams[3] = GL_FALSE; + for (int c = 0; c < components; c++) + { + SetIfDirty(boolParams + c, (v[c] == static_cast(0)) ? GL_FALSE : GL_TRUE, &targetUniform->dirty); + } + for (int c = components; c < 4; c++) + { + SetIfDirty(boolParams + c, GL_FALSE, &targetUniform->dirty); + } boolParams += 4; - v += 3; + v += components; } } - else - { - return false; - } - - return true; + else UNREACHABLE(); } -bool ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) +void ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat* v) { - if (location < 0 || location >= (int)mUniformIndex.size()) - { - return false; - } + setUniform(location, count, v, GL_FLOAT); +} - Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; - targetUniform->dirty = true; +void ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) +{ + setUniform(location, count, v, GL_FLOAT_VEC2); +} - int elementCount = targetUniform->elementCount(); +void ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) +{ + setUniform(location, count, v, GL_FLOAT_VEC3); +} - if (elementCount == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION +void ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) +{ + setUniform(location, count, v, GL_FLOAT_VEC4); +} - count = std::min(elementCount - (int)mUniformIndex[location].element, count); +template +bool transposeMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight) +{ + bool dirty = false; + int copyWidth = std::min(targetHeight, srcWidth); + int copyHeight = std::min(targetWidth, srcHeight); - if (targetUniform->type == GL_FLOAT_VEC4) + for (int x = 0; x < copyWidth; x++) { - GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) + for (int y = 0; y < copyHeight; y++) { - target[0] = v[0]; - target[1] = v[1]; - target[2] = v[2]; - target[3] = v[3]; - target += 4; - v += 4; + SetIfDirty(target + (x * targetWidth + y), static_cast(value[y * srcWidth + x]), &dirty); } } - else if (targetUniform->type == GL_BOOL_VEC4) + // clear unfilled right side + for (int y = 0; y < copyWidth; y++) { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) + for (int x = copyHeight; x < targetWidth; x++) { - boolParams[0] = (v[0] == 0.0f) ? GL_FALSE : GL_TRUE; - boolParams[1] = (v[1] == 0.0f) ? GL_FALSE : GL_TRUE; - boolParams[2] = (v[2] == 0.0f) ? GL_FALSE : GL_TRUE; - boolParams[3] = (v[3] == 0.0f) ? GL_FALSE : GL_TRUE; - boolParams += 4; - v += 4; + SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); } } - else + // clear unfilled bottom. + for (int y = copyWidth; y < targetHeight; y++) { - return false; + for (int x = 0; x < targetWidth; x++) + { + SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); + } } - return true; + return dirty; } -template -void transposeMatrix(T *target, const GLfloat *value) +template +bool expandMatrix(T *target, const GLfloat *value, int targetWidth, int targetHeight, int srcWidth, int srcHeight) { + bool dirty = false; int copyWidth = std::min(targetWidth, srcWidth); int copyHeight = std::min(targetHeight, srcHeight); - for (int x = 0; x < copyWidth; x++) + for (int y = 0; y < copyHeight; y++) { - for (int y = 0; y < copyHeight; y++) + for (int x = 0; x < copyWidth; x++) { - target[x * targetWidth + y] = (T)value[y * srcWidth + x]; + SetIfDirty(target + (y * targetWidth + x), static_cast(value[y * srcWidth + x]), &dirty); } } // clear unfilled right side for (int y = 0; y < copyHeight; y++) { - for (int x = srcWidth; x < targetWidth; x++) + for (int x = copyWidth; x < targetWidth; x++) { - target[y * targetWidth + x] = (T)0; + SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); } } // clear unfilled bottom. - for (int y = srcHeight; y < targetHeight; y++) + for (int y = copyHeight; y < targetHeight; y++) { for (int x = 0; x < targetWidth; x++) { - target[y * targetWidth + x] = (T)0; + SetIfDirty(target + (y * targetWidth + x), static_cast(0), &dirty); } } + + return dirty; } -bool ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value) +template +void ProgramBinary::setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType) { - if (location < 0 || location >= (int)mUniformIndex.size()) - { - return false; - } - - Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; - targetUniform->dirty = true; - - if (targetUniform->type != GL_FLOAT_MAT2) - { - return false; - } + LinkedUniform *targetUniform = getUniformByLocation(location); int elementCount = targetUniform->elementCount(); - if (elementCount == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - count = std::min(elementCount - (int)mUniformIndex[location].element, count); - GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8; + const unsigned int targetMatrixStride = (4 * rows); + GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * targetMatrixStride); for (int i = 0; i < count; i++) { - transposeMatrix(target, value); - target += 8; - value += 4; + // Internally store matrices as transposed versions to accomodate HLSL matrix indexing + if (transpose == GL_FALSE) + { + targetUniform->dirty = transposeMatrix(target, value, 4, rows, rows, cols) || targetUniform->dirty; + } + else + { + targetUniform->dirty = expandMatrix(target, value, 4, rows, cols, rows) || targetUniform->dirty; + } + target += targetMatrixStride; + value += cols * rows; } +} - return true; +void ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<2, 2>(location, count, transpose, value, GL_FLOAT_MAT2); } -bool ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value) +void ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { - if (location < 0 || location >= (int)mUniformIndex.size()) - { - return false; - } - - Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; - targetUniform->dirty = true; - - if (targetUniform->type != GL_FLOAT_MAT3) - { - return false; - } - - int elementCount = targetUniform->elementCount(); - - if (elementCount == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(elementCount - (int)mUniformIndex[location].element, count); - GLfloat *target = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12; - - for (int i = 0; i < count; i++) - { - transposeMatrix(target, value); - target += 12; - value += 9; - } - - return true; + setUniformMatrixfv<3, 3>(location, count, transpose, value, GL_FLOAT_MAT3); } - -bool ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value) +void ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { - if (location < 0 || location >= (int)mUniformIndex.size()) - { - return false; - } - - Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; - targetUniform->dirty = true; - - if (targetUniform->type != GL_FLOAT_MAT4) - { - return false; - } + setUniformMatrixfv<4, 4>(location, count, transpose, value, GL_FLOAT_MAT4); +} - int elementCount = targetUniform->elementCount(); +void ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<2, 3>(location, count, transpose, value, GL_FLOAT_MAT2x3); +} - if (elementCount == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION +void ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<3, 2>(location, count, transpose, value, GL_FLOAT_MAT3x2); +} - count = std::min(elementCount - (int)mUniformIndex[location].element, count); - GLfloat *target = (GLfloat*)(targetUniform->data + mUniformIndex[location].element * sizeof(GLfloat) * 16); +void ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<2, 4>(location, count, transpose, value, GL_FLOAT_MAT2x4); +} - for (int i = 0; i < count; i++) - { - transposeMatrix(target, value); - target += 16; - value += 16; - } +void ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<4, 2>(location, count, transpose, value, GL_FLOAT_MAT4x2); +} - return true; +void ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) +{ + setUniformMatrixfv<3, 4>(location, count, transpose, value, GL_FLOAT_MAT3x4); } -bool ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) +void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value) { - if (location < 0 || location >= (int)mUniformIndex.size()) - { - return false; - } + setUniformMatrixfv<4, 3>(location, count, transpose, value, GL_FLOAT_MAT4x3); +} - Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; - targetUniform->dirty = true; +void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) +{ + LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index]; int elementCount = targetUniform->elementCount(); - if (elementCount == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - count = std::min(elementCount - (int)mUniformIndex[location].element, count); - if (targetUniform->type == GL_INT || - targetUniform->type == GL_SAMPLER_2D || - targetUniform->type == GL_SAMPLER_CUBE) + if (targetUniform->type == GL_INT || IsSampler(targetUniform->type)) { GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; for (int i = 0; i < count; i++) { - target[0] = v[0]; - target[1] = 0; - target[2] = 0; - target[3] = 0; + 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; } @@ -633,317 +787,157 @@ bool ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) for (int i = 0; i < count; i++) { - boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE; - boolParams[1] = GL_FALSE; - boolParams[2] = GL_FALSE; - boolParams[3] = GL_FALSE; + 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 + else UNREACHABLE(); + + // Set a special flag if we change a sampler uniform + if (IsSampler(targetUniform->type) && + (memcmp(targetUniform->data, v, sizeof(GLint)) != 0)) { - return false; + mDirtySamplerMapping = true; } - - return true; } -bool ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) +void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) { - if (location < 0 || location >= (int)mUniformIndex.size()) - { - return false; - } - - Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; - targetUniform->dirty = true; - - int elementCount = targetUniform->elementCount(); - - if (elementCount == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(elementCount - (int)mUniformIndex[location].element, count); - - if (targetUniform->type == GL_INT_VEC2) - { - GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - target[0] = v[0]; - target[1] = v[1]; - target[2] = 0; - target[3] = 0; - target += 4; - v += 2; - } - } - else if (targetUniform->type == GL_BOOL_VEC2) - { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE; - boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE; - boolParams[2] = GL_FALSE; - boolParams[3] = GL_FALSE; - boolParams += 4; - v += 2; - } - } - else - { - return false; - } - - return true; + setUniform(location, count, v, GL_INT_VEC2); } -bool ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v) +void ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v) { - if (location < 0 || location >= (int)mUniformIndex.size()) - { - return false; - } - - Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; - targetUniform->dirty = true; - - int elementCount = targetUniform->elementCount(); - - if (elementCount == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(elementCount - (int)mUniformIndex[location].element, count); - - if (targetUniform->type == GL_INT_VEC3) - { - GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - target[0] = v[0]; - target[1] = v[1]; - target[2] = v[2]; - target[3] = 0; - target += 4; - v += 3; - } - } - else if (targetUniform->type == GL_BOOL_VEC3) - { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (int i = 0; i < count; i++) - { - boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE; - boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE; - boolParams[2] = (v[2] == 0) ? GL_FALSE : GL_TRUE; - boolParams[3] = GL_FALSE; - boolParams += 4; - v += 3; - } - } - else - { - return false; - } - - return true; + setUniform(location, count, v, GL_INT_VEC3); } -bool ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v) +void ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v) { - if (location < 0 || location >= (int)mUniformIndex.size()) - { - return false; - } - - Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; - targetUniform->dirty = true; - - int elementCount = targetUniform->elementCount(); - - if (elementCount == 1 && count > 1) - return false; // attempting to write an array to a non-array uniform is an INVALID_OPERATION - - count = std::min(elementCount - (int)mUniformIndex[location].element, count); - - if (targetUniform->type == GL_INT_VEC4) - { - GLint *target = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; + setUniform(location, count, v, GL_INT_VEC4); +} - for (int i = 0; i < count; i++) - { - target[0] = v[0]; - target[1] = v[1]; - target[2] = v[2]; - target[3] = v[3]; - target += 4; - v += 4; - } - } - else if (targetUniform->type == GL_BOOL_VEC4) - { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; +void ProgramBinary::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) +{ + setUniform(location, count, v, GL_UNSIGNED_INT); +} - for (int i = 0; i < count; i++) - { - boolParams[0] = (v[0] == 0) ? GL_FALSE : GL_TRUE; - boolParams[1] = (v[1] == 0) ? GL_FALSE : GL_TRUE; - boolParams[2] = (v[2] == 0) ? GL_FALSE : GL_TRUE; - boolParams[3] = (v[3] == 0) ? GL_FALSE : GL_TRUE; - boolParams += 4; - v += 4; - } - } - else - { - return false; - } +void ProgramBinary::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) +{ + setUniform(location, count, v, GL_UNSIGNED_INT_VEC2); +} - return true; +void ProgramBinary::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) +{ + setUniform(location, count, v, GL_UNSIGNED_INT_VEC3); } -bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params) +void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) { - if (location < 0 || location >= (int)mUniformIndex.size()) - { - return false; - } + setUniform(location, count, v, GL_UNSIGNED_INT_VEC4); +} - Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; +template +bool ProgramBinary::getUniformv(GLint location, GLsizei *bufSize, T *params, GLenum uniformType) +{ + LinkedUniform *targetUniform = mUniforms[mUniformIndex[location].index]; // sized queries -- ensure the provided buffer is large enough if (bufSize) { - int requiredBytes = UniformExternalSize(targetUniform->type); + int requiredBytes = VariableExternalSize(targetUniform->type); if (*bufSize < requiredBytes) { return false; } } - switch (targetUniform->type) + if (IsMatrixType(targetUniform->type)) { - case GL_FLOAT_MAT2: - transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8); - break; - case GL_FLOAT_MAT3: - transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12); - break; - case GL_FLOAT_MAT4: - transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16); - break; - default: + const int rows = VariableRowCount(targetUniform->type); + const int cols = VariableColumnCount(targetUniform->type); + transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4 * rows, rows, cols, 4, rows); + } + else if (uniformType == VariableComponentType(targetUniform->type)) + { + unsigned int size = VariableComponentCount(targetUniform->type); + memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(T), + size * sizeof(T)); + } + else + { + unsigned int size = VariableComponentCount(targetUniform->type); + switch (VariableComponentType(targetUniform->type)) { - unsigned int size = UniformComponentCount(targetUniform->type); - - switch (UniformComponentType(targetUniform->type)) + case GL_BOOL: { - case GL_BOOL: - { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; + GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - for (unsigned int i = 0; i < size; i++) - { - params[i] = (boolParams[i] == GL_FALSE) ? 0.0f : 1.0f; - } - } - break; - case GL_FLOAT: - memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(GLfloat), - size * sizeof(GLfloat)); - break; - case GL_INT: + for (unsigned int i = 0; i < size; i++) { - GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = (float)intParams[i]; - } + params[i] = (boolParams[i] == GL_FALSE) ? static_cast(0) : static_cast(1); } - break; - default: UNREACHABLE(); } - } - } - - return true; -} + break; -bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params) -{ - if (location < 0 || location >= (int)mUniformIndex.size()) - { - return false; - } + case GL_FLOAT: + { + GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; - Uniform *targetUniform = mUniforms[mUniformIndex[location].index]; + for (unsigned int i = 0; i < size; i++) + { + params[i] = static_cast(floatParams[i]); + } + } + break; - // sized queries -- ensure the provided buffer is large enough - if (bufSize) - { - int requiredBytes = UniformExternalSize(targetUniform->type); - if (*bufSize < requiredBytes) - { - return false; - } - } + case GL_INT: + { + GLint *intParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; - switch (targetUniform->type) - { - case GL_FLOAT_MAT2: - transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 8); - break; - case GL_FLOAT_MAT3: - transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 12); - break; - case GL_FLOAT_MAT4: - transposeMatrix(params, (GLfloat*)targetUniform->data + mUniformIndex[location].element * 16); - break; - default: - { - unsigned int size = VariableColumnCount(targetUniform->type); + for (unsigned int i = 0; i < size; i++) + { + params[i] = static_cast(intParams[i]); + } + } + break; - switch (UniformComponentType(targetUniform->type)) + case GL_UNSIGNED_INT: { - case GL_BOOL: - { - GLint *boolParams = (GLint*)targetUniform->data + mUniformIndex[location].element * 4; + GLuint *uintParams = (GLuint*)targetUniform->data + mUniformIndex[location].element * 4; - for (unsigned int i = 0; i < size; i++) - { - params[i] = boolParams[i]; - } - } - break; - case GL_FLOAT: + for (unsigned int i = 0; i < size; i++) { - GLfloat *floatParams = (GLfloat*)targetUniform->data + mUniformIndex[location].element * 4; - - for (unsigned int i = 0; i < size; i++) - { - params[i] = (GLint)floatParams[i]; - } + params[i] = static_cast(uintParams[i]); } - break; - case GL_INT: - memcpy(params, targetUniform->data + mUniformIndex[location].element * 4 * sizeof(GLint), - size * sizeof(GLint)); - break; - default: UNREACHABLE(); } + break; + + default: UNREACHABLE(); } } return true; } +bool ProgramBinary::getUniformfv(GLint location, GLsizei *bufSize, GLfloat *params) +{ + return getUniformv(location, bufSize, params, GL_FLOAT); +} + +bool ProgramBinary::getUniformiv(GLint location, GLsizei *bufSize, GLint *params) +{ + return getUniformv(location, bufSize, params, GL_INT); +} + +bool ProgramBinary::getUniformuiv(GLint location, GLsizei *bufSize, GLuint *params) +{ + return getUniformv(location, bufSize, params, GL_UNSIGNED_INT); +} + void ProgramBinary::dirtyAllUniforms() { unsigned int numUniforms = mUniforms.size(); @@ -953,23 +947,28 @@ void ProgramBinary::dirtyAllUniforms() } } -// Applies all the uniforms set for this program object to the renderer -void ProgramBinary::applyUniforms() +void ProgramBinary::updateSamplerMapping() { + if (!mDirtySamplerMapping) + { + return; + } + + mDirtySamplerMapping = false; + // Retrieve sampler uniform values - for (std::vector::iterator ub = mUniforms.begin(), ue = mUniforms.end(); ub != ue; ++ub) + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) { - Uniform *targetUniform = *ub; + LinkedUniform *targetUniform = mUniforms[uniformIndex]; if (targetUniform->dirty) { - if (targetUniform->type == GL_SAMPLER_2D || - targetUniform->type == GL_SAMPLER_CUBE) + if (IsSampler(targetUniform->type)) { int count = targetUniform->elementCount(); - GLint (*v)[4] = (GLint(*)[4])targetUniform->data; + GLint (*v)[4] = reinterpret_cast(targetUniform->data); - if (targetUniform->psRegisterIndex >= 0) + if (targetUniform->isReferencedByFragmentShader()) { unsigned int firstIndex = targetUniform->psRegisterIndex; @@ -985,7 +984,7 @@ void ProgramBinary::applyUniforms() } } - if (targetUniform->vsRegisterIndex >= 0) + if (targetUniform->isReferencedByVertexShader()) { unsigned int firstIndex = targetUniform->vsRegisterIndex; @@ -1003,215 +1002,87 @@ void ProgramBinary::applyUniforms() } } } +} + +// Applies all the uniforms set for this program object to the renderer +void ProgramBinary::applyUniforms() +{ + updateSamplerMapping(); - mRenderer->applyUniforms(this, &mUniforms); + mRenderer->applyUniforms(*this); + + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + { + mUniforms[uniformIndex]->dirty = 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 ProgramBinary::packVaryings(InfoLog &infoLog, const Varying *packing[][4], FragmentShader *fragmentShader) +bool ProgramBinary::applyUniformBuffers(const std::vector boundBuffers) { - const int maxVaryingVectors = mRenderer->getMaxVaryingVectors(); + 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(); - fragmentShader->resetVaryingsRegisterAssignment(); + ASSERT(boundBuffers.size() == mUniformBlocks.size()); - for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++) + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++) { - int n = VariableRowCount(varying->type) * varying->size; - int m = VariableColumnCount(varying->type); - bool success = false; + UniformBlock *uniformBlock = getUniformBlockByIndex(uniformBlockIndex); + gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex]; - if (m == 2 || m == 3 || m == 4) + ASSERT(uniformBlock && uniformBuffer); + + if (uniformBuffer->getSize() < uniformBlock->dataSize) { - for (int r = 0; r <= maxVaryingVectors - n && !success; r++) - { - bool available = true; + // undefined behaviour + return false; + } - for (int y = 0; y < n && available; y++) - { - for (int x = 0; x < m && available; x++) - { - if (packing[r + y][x]) - { - available = false; - } - } - } - - if (available) - { - varying->reg = r; - varying->col = 0; - - for (int y = 0; y < n; y++) - { - for (int x = 0; x < m; x++) - { - packing[r + y][x] = &*varying; - } - } - - success = true; - } - } - - if (!success && m == 2) - { - for (int r = maxVaryingVectors - n; r >= 0 && !success; r--) - { - bool available = true; - - for (int y = 0; y < n && available; y++) - { - for (int x = 2; x < 4 && available; x++) - { - if (packing[r + y][x]) - { - available = false; - } - } - } - - if (available) - { - varying->reg = r; - varying->col = 2; - - for (int y = 0; y < n; y++) - { - for (int x = 2; x < 4; x++) - { - packing[r + y][x] = &*varying; - } - } - - success = true; - } - } - } - } - else if (m == 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] >= n && space[x] < space[column]) - { - column = x; - } - } - - if (space[column] >= n) - { - for (int r = 0; r < maxVaryingVectors; r++) - { - if (!packing[r][column]) - { - varying->reg = r; - - for (int y = r; y < r + n; y++) - { - packing[y][column] = &*varying; - } - - break; - } - } + ASSERT(uniformBlock->isReferencedByVertexShader() || uniformBlock->isReferencedByFragmentShader()); - varying->col = column; - - success = true; - } - } - else UNREACHABLE(); - - if (!success) + if (uniformBlock->isReferencedByVertexShader()) { - infoLog.append("Could not pack varying %s", varying->name.c_str()); - - return -1; + unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS; + ASSERT(vertexUniformBuffers[registerIndex] == NULL); + ASSERT(registerIndex < mRenderer->getMaxVertexShaderUniformBuffers()); + vertexUniformBuffers[registerIndex] = uniformBuffer; } - } - - // 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]) + if (uniformBlock->isReferencedByFragmentShader()) { - registers++; + unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS; + ASSERT(fragmentUniformBuffers[registerIndex] == NULL); + ASSERT(registerIndex < mRenderer->getMaxFragmentShaderUniformBuffers()); + fragmentUniformBuffers[registerIndex] = uniformBuffer; } } - return registers; + return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers); } -bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying *packing[][4], - std::string& pixelHLSL, std::string& vertexHLSL, - FragmentShader *fragmentShader, VertexShader *vertexShader) +bool ProgramBinary::linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader) { - if (pixelHLSL.empty() || vertexHLSL.empty()) - { - return false; - } + std::vector &fragmentVaryings = fragmentShader->getVaryings(); + std::vector &vertexVaryings = vertexShader->getVaryings(); - bool usesMRT = fragmentShader->mUsesMultipleRenderTargets; - bool usesFragColor = fragmentShader->mUsesFragColor; - bool usesFragData = fragmentShader->mUsesFragData; - 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 + (fragmentShader->mUsesFragCoord ? 1 : 0) + (fragmentShader->mUsesPointCoord ? 1 : 0); - - // The output color is broadcast to all enabled draw buffers when writing to gl_FragColor - const bool broadcast = fragmentShader->mUsesFragColor; - const unsigned int numRenderTargets = (broadcast || usesMRT ? mRenderer->getMaxRenderTargets() : 1); - - if (registersNeeded > maxVaryingVectors) - { - infoLog.append("No varying registers left to support gl_FragCoord/gl_PointCoord"); - - return false; - } - - vertexShader->resetVaryingsRegisterAssignment(); - - for (VaryingList::iterator input = fragmentShader->mVaryings.begin(); input != fragmentShader->mVaryings.end(); input++) + for (size_t fragVaryingIndex = 0; fragVaryingIndex < fragmentVaryings.size(); fragVaryingIndex++) { + PackedVarying *input = &fragmentVaryings[fragVaryingIndex]; bool matched = false; - for (VaryingList::iterator output = vertexShader->mVaryings.begin(); output != vertexShader->mVaryings.end(); output++) + for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++) { + PackedVarying *output = &vertexVaryings[vertVaryingIndex]; if (output->name == input->name) { - if (output->type != input->type || output->size != input->size) + if (!linkValidateVariables(infoLog, output->name, *input, *output)) { - infoLog.append("Type of vertex varying %s does not match that of the fragment varying", output->name.c_str()); - return false; } - output->reg = input->reg; - output->col = input->col; + output->registerIndex = input->registerIndex; matched = true; break; @@ -1221,530 +1092,274 @@ bool ProgramBinary::linkVaryings(InfoLog &infoLog, int registers, const Varying if (!matched) { infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str()); - return false; } } - mUsesPointSize = vertexShader->mUsesPointSize; - std::string varyingSemantic = (mUsesPointSize && shaderModel == 3) ? "COLOR" : "TEXCOORD"; - std::string targetSemantic = (shaderModel >= 4) ? "SV_Target" : "COLOR"; - std::string positionSemantic = (shaderModel >= 4) ? "SV_Position" : "POSITION"; - std::string depthSemantic = (shaderModel >= 4) ? "SV_Depth" : "DEPTH"; - - // special varyings that use reserved registers - int reservedRegisterIndex = registers; - std::string fragCoordSemantic; - std::string pointCoordSemantic; - - if (fragmentShader->mUsesFragCoord) - { - fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); - } - - if (fragmentShader->mUsesPointCoord) - { - // Shader model 3 uses a special TEXCOORD semantic for point sprite texcoords. - // In DX11 we compute this in the GS. - if (shaderModel == 3) - { - pointCoordSemantic = "TEXCOORD0"; - } - else if (shaderModel >= 4) - { - pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); - } - } - - vertexHLSL += "struct VS_INPUT\n" - "{\n"; - - int semanticIndex = 0; - for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++) - { - switch (attribute->type) - { - case GL_FLOAT: vertexHLSL += " float "; break; - case GL_FLOAT_VEC2: vertexHLSL += " float2 "; break; - case GL_FLOAT_VEC3: vertexHLSL += " float3 "; break; - case GL_FLOAT_VEC4: vertexHLSL += " float4 "; break; - case GL_FLOAT_MAT2: vertexHLSL += " float2x2 "; break; - case GL_FLOAT_MAT3: vertexHLSL += " float3x3 "; break; - case GL_FLOAT_MAT4: vertexHLSL += " float4x4 "; break; - default: UNREACHABLE(); - } - - vertexHLSL += decorateAttribute(attribute->name) + " : TEXCOORD" + str(semanticIndex) + ";\n"; + return true; +} - semanticIndex += VariableRowCount(attribute->type); - } +bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) +{ +#ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD + return false; +#else + reset(); - vertexHLSL += "};\n" - "\n" - "struct VS_OUTPUT\n" - "{\n"; + BinaryInputStream stream(binary, length); - if (shaderModel < 4) + int format = stream.readInt(); + if (format != GL_PROGRAM_BINARY_ANGLE) { - vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n"; + infoLog.append("Invalid program binary format."); + return false; } - for (int r = 0; r < registers; r++) + int majorVersion = stream.readInt(); + int minorVersion = stream.readInt(); + if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION) { - int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1)); - - vertexHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n"; + infoLog.append("Invalid program binary version."); + return false; } - if (fragmentShader->mUsesFragCoord) + unsigned char commitString[ANGLE_COMMIT_HASH_SIZE]; + stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE); + if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0) { - vertexHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; + infoLog.append("Invalid program binary version."); + return false; } - if (vertexShader->mUsesPointSize && shaderModel >= 3) + int compileFlags = stream.readInt(); + if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL) { - vertexHLSL += " float gl_PointSize : PSIZE;\n"; + infoLog.append("Mismatched compilation flags."); + return false; } - if (shaderModel >= 4) + for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) { - vertexHLSL += " float4 gl_Position : " + positionSemantic + ";\n"; + stream.readInt(&mLinkedAttribute[i].type); + stream.readString(&mLinkedAttribute[i].name); + stream.readInt(&mShaderAttributes[i].type); + stream.readString(&mShaderAttributes[i].name); + stream.readInt(&mSemanticIndex[i]); } - vertexHLSL += "};\n" - "\n" - "VS_OUTPUT main(VS_INPUT input)\n" - "{\n"; + initAttributesByLayout(); - for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++) + for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) { - vertexHLSL += " " + decorateAttribute(attribute->name) + " = "; - - if (VariableRowCount(attribute->type) > 1) // Matrix - { - vertexHLSL += "transpose"; - } - - vertexHLSL += "(input." + decorateAttribute(attribute->name) + ");\n"; + stream.readBool(&mSamplersPS[i].active); + stream.readInt(&mSamplersPS[i].logicalTextureUnit); + stream.readInt(&mSamplersPS[i].textureType); } - if (shaderModel >= 4) - { - vertexHLSL += "\n" - " gl_main();\n" - "\n" - " VS_OUTPUT output;\n" - " output.gl_Position.x = gl_Position.x;\n" - " output.gl_Position.y = -gl_Position.y;\n" - " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" - " output.gl_Position.w = gl_Position.w;\n"; - } - else + for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) { - vertexHLSL += "\n" - " gl_main();\n" - "\n" - " VS_OUTPUT output;\n" - " output.gl_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n" - " output.gl_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n" - " output.gl_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n" - " output.gl_Position.w = gl_Position.w;\n"; + stream.readBool(&mSamplersVS[i].active); + stream.readInt(&mSamplersVS[i].logicalTextureUnit); + stream.readInt(&mSamplersVS[i].textureType); } - if (vertexShader->mUsesPointSize && shaderModel >= 3) - { - vertexHLSL += " output.gl_PointSize = gl_PointSize;\n"; - } + stream.readInt(&mUsedVertexSamplerRange); + stream.readInt(&mUsedPixelSamplerRange); + stream.readBool(&mUsesPointSize); + stream.readInt(&mShaderVersion); - if (fragmentShader->mUsesFragCoord) + const unsigned int uniformCount = stream.readInt(); + if (stream.error()) { - vertexHLSL += " output.gl_FragCoord = gl_Position;\n"; + infoLog.append("Invalid program binary."); + return false; } - for (VaryingList::iterator varying = vertexShader->mVaryings.begin(); varying != vertexShader->mVaryings.end(); varying++) + mUniforms.resize(uniformCount); + for (unsigned int uniformIndex = 0; uniformIndex < uniformCount; uniformIndex++) { - if (varying->reg >= 0) - { - for (int i = 0; i < varying->size; i++) - { - int rows = VariableRowCount(varying->type); - - for (int j = 0; j < rows; j++) - { - int r = varying->reg + i * rows + j; - vertexHLSL += " output.v" + str(r); + GLenum type = stream.readInt(); + GLenum precision = stream.readInt(); + std::string name = stream.readString(); + unsigned int arraySize = stream.readInt(); + int blockIndex = stream.readInt(); - 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; - } - } + int offset = stream.readInt(); + int arrayStride = stream.readInt(); + int matrixStride = stream.readInt(); + bool isRowMajorMatrix = stream.readBool(); - 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->array) - { - vertexHLSL += "[" + str(i) + "]"; - } + const sh::BlockMemberInfo blockInfo(offset, arrayStride, matrixStride, isRowMajorMatrix); - if (rows > 1) - { - vertexHLSL += "[" + str(j) + "]"; - } - - vertexHLSL += ";\n"; - } - } - } - } + LinkedUniform *uniform = new LinkedUniform(type, precision, name, arraySize, blockIndex, blockInfo); - vertexHLSL += "\n" - " return output;\n" - "}\n"; + stream.readInt(&uniform->psRegisterIndex); + stream.readInt(&uniform->vsRegisterIndex); + stream.readInt(&uniform->registerCount); + stream.readInt(&uniform->registerElement); - pixelHLSL += "struct PS_INPUT\n" - "{\n"; - - for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++) - { - if (varying->reg >= 0) - { - for (int i = 0; i < varying->size; i++) - { - int rows = VariableRowCount(varying->type); - for (int j = 0; j < rows; j++) - { - std::string n = str(varying->reg + i * rows + j); - pixelHLSL += " float" + str(VariableColumnCount(varying->type)) + " v" + n + " : " + varyingSemantic + n + ";\n"; - } - } - } - else UNREACHABLE(); + mUniforms[uniformIndex] = uniform; } - if (fragmentShader->mUsesFragCoord) - { - pixelHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; - } - - if (fragmentShader->mUsesPointCoord && shaderModel >= 3) - { - pixelHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n"; - } - - // Must consume the PSIZE element if the geometry shader is not active - // We won't know if we use a GS until we draw - if (vertexShader->mUsesPointSize && shaderModel >= 4) - { - pixelHLSL += " float gl_PointSize : PSIZE;\n"; - } - - if (fragmentShader->mUsesFragCoord) + unsigned int uniformBlockCount = stream.readInt(); + if (stream.error()) { - if (shaderModel >= 4) - { - pixelHLSL += " float4 dx_VPos : SV_Position;\n"; - } - else if (shaderModel >= 3) - { - pixelHLSL += " float2 dx_VPos : VPOS;\n"; - } + infoLog.append("Invalid program binary."); + return false; } - pixelHLSL += "};\n" - "\n" - "struct PS_OUTPUT\n" - "{\n"; - - for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++) + mUniformBlocks.resize(uniformBlockCount); + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < uniformBlockCount; ++uniformBlockIndex) { - pixelHLSL += " float4 gl_Color" + str(renderTargetIndex) + " : " + targetSemantic + str(renderTargetIndex) + ";\n"; - } + std::string name = stream.readString(); + unsigned int elementIndex = stream.readInt(); + unsigned int dataSize = stream.readInt(); - if (fragmentShader->mUsesFragDepth) - { - pixelHLSL += " float gl_Depth : " + depthSemantic + ";\n"; - } + UniformBlock *uniformBlock = new UniformBlock(name, elementIndex, dataSize); - pixelHLSL += "};\n" - "\n"; + stream.readInt(&uniformBlock->psRegisterIndex); + stream.readInt(&uniformBlock->vsRegisterIndex); - 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 (fragmentShader->mUsesFragCoord) - { - pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n"; - - if (shaderModel >= 4) - { - pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x;\n" - " gl_FragCoord.y = input.dx_VPos.y;\n"; - } - else if (shaderModel >= 3) - { - pixelHLSL += " gl_FragCoord.x = input.dx_VPos.x + 0.5;\n" - " gl_FragCoord.y = input.dx_VPos.y + 0.5;\n"; - } - else + unsigned int numMembers = stream.readInt(); + uniformBlock->memberUniformIndexes.resize(numMembers); + for (unsigned int blockMemberIndex = 0; blockMemberIndex < numMembers; blockMemberIndex++) { - // 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"; + stream.readInt(&uniformBlock->memberUniformIndexes[blockMemberIndex]); } - - pixelHLSL += " gl_FragCoord.z = (input.gl_FragCoord.z * rhw) * dx_DepthFront.x + dx_DepthFront.y;\n" - " gl_FragCoord.w = rhw;\n"; - } - if (fragmentShader->mUsesPointCoord && shaderModel >= 3) - { - pixelHLSL += " gl_PointCoord.x = input.gl_PointCoord.x;\n"; - pixelHLSL += " gl_PointCoord.y = 1.0 - input.gl_PointCoord.y;\n"; + mUniformBlocks[uniformBlockIndex] = uniformBlock; } - if (fragmentShader->mUsesFrontFacing) + const unsigned int uniformIndexCount = stream.readInt(); + if (stream.error()) { - if (shaderModel <= 3) - { - pixelHLSL += " gl_FrontFacing = (vFace * dx_DepthFront.z >= 0.0);\n"; - } - else - { - pixelHLSL += " gl_FrontFacing = isFrontFace;\n"; - } + infoLog.append("Invalid program binary."); + return false; } - for (VaryingList::iterator varying = fragmentShader->mVaryings.begin(); varying != fragmentShader->mVaryings.end(); varying++) + mUniformIndex.resize(uniformIndexCount); + for (unsigned int uniformIndexIndex = 0; uniformIndexIndex < uniformIndexCount; uniformIndexIndex++) { - if (varying->reg >= 0) - { - for (int i = 0; i < varying->size; i++) - { - int rows = VariableRowCount(varying->type); - for (int j = 0; j < rows; j++) - { - std::string n = str(varying->reg + i * rows + j); - pixelHLSL += " " + varying->name; - - if (varying->array) - { - pixelHLSL += "[" + str(i) + "]"; - } - - if (rows > 1) - { - pixelHLSL += "[" + str(j) + "]"; - } - - switch (VariableColumnCount(varying->type)) - { - case 1: pixelHLSL += " = input.v" + n + ".x;\n"; break; - case 2: pixelHLSL += " = input.v" + n + ".xy;\n"; break; - case 3: pixelHLSL += " = input.v" + n + ".xyz;\n"; break; - case 4: pixelHLSL += " = input.v" + n + ";\n"; break; - default: UNREACHABLE(); - } - } - } - } - else UNREACHABLE(); + stream.readString(&mUniformIndex[uniformIndexIndex].name); + stream.readInt(&mUniformIndex[uniformIndexIndex].element); + stream.readInt(&mUniformIndex[uniformIndexIndex].index); } - pixelHLSL += "\n" - " gl_main();\n" - "\n" - " PS_OUTPUT output;\n"; - - for (unsigned int renderTargetIndex = 0; renderTargetIndex < numRenderTargets; renderTargetIndex++) + stream.readInt(&mTransformFeedbackBufferMode); + const unsigned int transformFeedbackVaryingCount = stream.readInt(); + mTransformFeedbackLinkedVaryings.resize(transformFeedbackVaryingCount); + for (unsigned int varyingIndex = 0; varyingIndex < transformFeedbackVaryingCount; varyingIndex++) { - unsigned int sourceColorIndex = broadcast ? 0 : renderTargetIndex; - - pixelHLSL += " output.gl_Color" + str(renderTargetIndex) + " = gl_Color[" + str(sourceColorIndex) + "];\n"; - } + LinkedVarying &varying = mTransformFeedbackLinkedVaryings[varyingIndex]; - if (fragmentShader->mUsesFragDepth) - { - pixelHLSL += " output.gl_Depth = gl_Depth;\n"; + stream.readString(&varying.name); + stream.readInt(&varying.type); + stream.readInt(&varying.size); + stream.readString(&varying.semanticName); + stream.readInt(&varying.semanticIndex); + stream.readInt(&varying.semanticIndexCount); } - pixelHLSL += "\n" - " return output;\n" - "}\n"; + stream.readString(&mVertexHLSL); - return true; -} + stream.readInt(&mVertexWorkarounds); -bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) -{ - BinaryInputStream stream(binary, length); - - int format = 0; - stream.read(&format); - if (format != GL_PROGRAM_BINARY_ANGLE) + const unsigned int vertexShaderCount = stream.readInt(); + for (unsigned int vertexShaderIndex = 0; vertexShaderIndex < vertexShaderCount; vertexShaderIndex++) { - infoLog.append("Invalid program binary format."); - return false; - } + VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]; - int majorVersion = 0; - int minorVersion = 0; - stream.read(&majorVersion); - stream.read(&minorVersion); - if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION) - { - infoLog.append("Invalid program binary version."); - return false; - } - -#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY) - unsigned char commitString[ANGLE_COMMIT_HASH_SIZE]; - stream.read(commitString, ANGLE_COMMIT_HASH_SIZE); - if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0) - { - infoLog.append("Invalid program binary version."); - return false; - } - - int compileFlags = 0; - stream.read(&compileFlags); - if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL) - { - infoLog.append("Mismatched compilation flags."); - return false; - } -#endif + for (size_t inputIndex = 0; inputIndex < MAX_VERTEX_ATTRIBS; inputIndex++) + { + VertexFormat *vertexInput = &inputLayout[inputIndex]; + stream.readInt(&vertexInput->mType); + stream.readInt(&vertexInput->mNormalized); + stream.readInt(&vertexInput->mComponents); + stream.readBool(&vertexInput->mPureInteger); + } - for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) - { - stream.read(&mLinkedAttribute[i].type); - std::string name; - stream.read(&name); - mLinkedAttribute[i].name = name; - stream.read(&mSemanticIndex[i]); - } + unsigned int vertexShaderSize = stream.readInt(); + const unsigned char *vertexShaderFunction = reinterpret_cast(binary) + stream.offset(); + rx::ShaderExecutable *shaderExecutable = mRenderer->loadExecutable(reinterpret_cast(vertexShaderFunction), + vertexShaderSize, rx::SHADER_VERTEX, + mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); + if (!shaderExecutable) + { + infoLog.append("Could not create vertex shader."); + return false; + } - initAttributesByLayout(); + // generated converted input layout + GLenum signature[MAX_VERTEX_ATTRIBS]; + mDynamicHLSL->getInputLayoutSignature(inputLayout, signature); - for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) - { - stream.read(&mSamplersPS[i].active); - stream.read(&mSamplersPS[i].logicalTextureUnit); - - int textureType; - stream.read(&textureType); - mSamplersPS[i].textureType = (TextureType) textureType; - } + // add new binary + mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, shaderExecutable)); - for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) - { - stream.read(&mSamplersVS[i].active); - stream.read(&mSamplersVS[i].logicalTextureUnit); - - int textureType; - stream.read(&textureType); - mSamplersVS[i].textureType = (TextureType) textureType; + stream.skip(vertexShaderSize); } - stream.read(&mUsedVertexSamplerRange); - stream.read(&mUsedPixelSamplerRange); - stream.read(&mUsesPointSize); + stream.readString(&mPixelHLSL); + stream.readInt(&mPixelWorkarounds); + stream.readBool(&mUsesFragDepth); - size_t size; - stream.read(&size); - if (stream.error()) + const size_t pixelShaderKeySize = stream.readInt(); + mPixelShaderKey.resize(pixelShaderKeySize); + for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < pixelShaderKeySize; pixelShaderKeyIndex++) { - infoLog.append("Invalid program binary."); - return false; + stream.readInt(&mPixelShaderKey[pixelShaderKeyIndex].type); + stream.readString(&mPixelShaderKey[pixelShaderKeyIndex].name); + stream.readString(&mPixelShaderKey[pixelShaderKeyIndex].source); + stream.readInt(&mPixelShaderKey[pixelShaderKeyIndex].outputIndex); } - mUniforms.resize(size); - for (unsigned int i = 0; i < size; ++i) + const size_t pixelShaderCount = stream.readInt(); + for (size_t pixelShaderIndex = 0; pixelShaderIndex < pixelShaderCount; pixelShaderIndex++) { - GLenum type; - GLenum precision; - std::string name; - unsigned int arraySize; + const size_t outputCount = stream.readInt(); + std::vector outputs(outputCount); + for (size_t outputIndex = 0; outputIndex < outputCount; outputIndex++) + { + stream.readInt(&outputs[outputIndex]); + } - stream.read(&type); - stream.read(&precision); - stream.read(&name); - stream.read(&arraySize); + 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)); + if (!shaderExecutable) + { + infoLog.append("Could not create pixel shader."); + return false; + } - mUniforms[i] = new Uniform(type, precision, name, arraySize); - - stream.read(&mUniforms[i]->psRegisterIndex); - stream.read(&mUniforms[i]->vsRegisterIndex); - stream.read(&mUniforms[i]->registerCount); - } + // add new binary + mPixelExecutables.push_back(new PixelExecutable(outputs, shaderExecutable)); - stream.read(&size); - if (stream.error()) - { - infoLog.append("Invalid program binary."); - return false; + stream.skip(pixelShaderSize); } - mUniformIndex.resize(size); - for (unsigned int i = 0; i < size; ++i) + unsigned int geometryShaderSize = stream.readInt(); + + if (geometryShaderSize > 0) { - stream.read(&mUniformIndex[i].name); - stream.read(&mUniformIndex[i].element); - stream.read(&mUniformIndex[i].index); + const char *geometryShaderFunction = (const char*) binary + stream.offset(); + mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast(geometryShaderFunction), + geometryShaderSize, rx::SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings, + (mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS)); + if (!mGeometryExecutable) + { + infoLog.append("Could not create geometry shader."); + return false; + } + stream.skip(geometryShaderSize); } - unsigned int pixelShaderSize; - stream.read(&pixelShaderSize); - - unsigned int vertexShaderSize; - stream.read(&vertexShaderSize); - - unsigned int geometryShaderSize; - stream.read(&geometryShaderSize); - const char *ptr = (const char*) binary + stream.offset(); -#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY) const GUID *binaryIdentifier = (const GUID *) ptr; ptr += sizeof(GUID); @@ -1754,131 +1369,186 @@ bool ProgramBinary::load(InfoLog &infoLog, const void *binary, GLsizei length) infoLog.append("Invalid program binary."); return false; } -#endif - const char *pixelShaderFunction = ptr; - ptr += pixelShaderSize; + initializeUniformStorage(); - const char *vertexShaderFunction = ptr; - ptr += vertexShaderSize; + return true; +#endif // #ifdef ANGLE_DISABLE_PROGRAM_BINARY_LOAD +} + +bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) +{ + BinaryOutputStream stream; - const char *geometryShaderFunction = geometryShaderSize > 0 ? ptr : NULL; - ptr += geometryShaderSize; + stream.writeInt(GL_PROGRAM_BINARY_ANGLE); + stream.writeInt(ANGLE_MAJOR_VERSION); + stream.writeInt(ANGLE_MINOR_VERSION); + stream.writeBytes(reinterpret_cast(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE); + stream.writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL); - mPixelExecutable = mRenderer->loadExecutable(reinterpret_cast(pixelShaderFunction), - pixelShaderSize, rx::SHADER_PIXEL); - if (!mPixelExecutable) + for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) { - infoLog.append("Could not create pixel shader."); - return false; + stream.writeInt(mLinkedAttribute[i].type); + stream.writeString(mLinkedAttribute[i].name); + stream.writeInt(mShaderAttributes[i].type); + stream.writeString(mShaderAttributes[i].name); + stream.writeInt(mSemanticIndex[i]); } - mVertexExecutable = mRenderer->loadExecutable(reinterpret_cast(vertexShaderFunction), - vertexShaderSize, rx::SHADER_VERTEX); - if (!mVertexExecutable) + for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) { - infoLog.append("Could not create vertex shader."); - delete mPixelExecutable; - mPixelExecutable = NULL; - return false; + stream.writeInt(mSamplersPS[i].active); + stream.writeInt(mSamplersPS[i].logicalTextureUnit); + stream.writeInt(mSamplersPS[i].textureType); } - if (geometryShaderFunction != NULL && geometryShaderSize > 0) + for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) { - mGeometryExecutable = mRenderer->loadExecutable(reinterpret_cast(geometryShaderFunction), - geometryShaderSize, rx::SHADER_GEOMETRY); - if (!mGeometryExecutable) - { - infoLog.append("Could not create geometry shader."); - delete mPixelExecutable; - mPixelExecutable = NULL; - delete mVertexExecutable; - mVertexExecutable = NULL; - return false; - } + stream.writeInt(mSamplersVS[i].active); + stream.writeInt(mSamplersVS[i].logicalTextureUnit); + stream.writeInt(mSamplersVS[i].textureType); } - else + + stream.writeInt(mUsedVertexSamplerRange); + stream.writeInt(mUsedPixelSamplerRange); + stream.writeInt(mUsesPointSize); + stream.writeInt(mShaderVersion); + + stream.writeInt(mUniforms.size()); + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); ++uniformIndex) { - mGeometryExecutable = NULL; - } + const LinkedUniform &uniform = *mUniforms[uniformIndex]; - return true; -} + stream.writeInt(uniform.type); + stream.writeInt(uniform.precision); + stream.writeString(uniform.name); + stream.writeInt(uniform.arraySize); + stream.writeInt(uniform.blockIndex); -bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) -{ - BinaryOutputStream stream; + stream.writeInt(uniform.blockInfo.offset); + stream.writeInt(uniform.blockInfo.arrayStride); + stream.writeInt(uniform.blockInfo.matrixStride); + stream.writeInt(uniform.blockInfo.isRowMajorMatrix); - stream.write(GL_PROGRAM_BINARY_ANGLE); - stream.write(ANGLE_MAJOR_VERSION); - stream.write(ANGLE_MINOR_VERSION); -#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY) - stream.write(ANGLE_COMMIT_HASH, ANGLE_COMMIT_HASH_SIZE); - stream.write(ANGLE_COMPILE_OPTIMIZATION_LEVEL); -#endif - for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i) + stream.writeInt(uniform.psRegisterIndex); + stream.writeInt(uniform.vsRegisterIndex); + stream.writeInt(uniform.registerCount); + stream.writeInt(uniform.registerElement); + } + + stream.writeInt(mUniformBlocks.size()); + for (size_t uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); ++uniformBlockIndex) { - stream.write(mLinkedAttribute[i].type); - stream.write(mLinkedAttribute[i].name); - stream.write(mSemanticIndex[i]); + const UniformBlock& uniformBlock = *mUniformBlocks[uniformBlockIndex]; + + stream.writeString(uniformBlock.name); + stream.writeInt(uniformBlock.elementIndex); + stream.writeInt(uniformBlock.dataSize); + + stream.writeInt(uniformBlock.memberUniformIndexes.size()); + for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++) + { + stream.writeInt(uniformBlock.memberUniformIndexes[blockMemberIndex]); + } + + stream.writeInt(uniformBlock.psRegisterIndex); + stream.writeInt(uniformBlock.vsRegisterIndex); } - for (unsigned int i = 0; i < MAX_TEXTURE_IMAGE_UNITS; ++i) + stream.writeInt(mUniformIndex.size()); + for (size_t i = 0; i < mUniformIndex.size(); ++i) { - stream.write(mSamplersPS[i].active); - stream.write(mSamplersPS[i].logicalTextureUnit); - stream.write((int) mSamplersPS[i].textureType); + stream.writeString(mUniformIndex[i].name); + stream.writeInt(mUniformIndex[i].element); + stream.writeInt(mUniformIndex[i].index); } - for (unsigned int i = 0; i < IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; ++i) + stream.writeInt(mTransformFeedbackBufferMode); + stream.writeInt(mTransformFeedbackLinkedVaryings.size()); + for (size_t i = 0; i < mTransformFeedbackLinkedVaryings.size(); i++) { - stream.write(mSamplersVS[i].active); - stream.write(mSamplersVS[i].logicalTextureUnit); - stream.write((int) mSamplersVS[i].textureType); + const LinkedVarying &varying = mTransformFeedbackLinkedVaryings[i]; + + stream.writeString(varying.name); + stream.writeInt(varying.type); + stream.writeInt(varying.size); + stream.writeString(varying.semanticName); + stream.writeInt(varying.semanticIndex); + stream.writeInt(varying.semanticIndexCount); } - stream.write(mUsedVertexSamplerRange); - stream.write(mUsedPixelSamplerRange); - stream.write(mUsesPointSize); + stream.writeString(mVertexHLSL); + stream.writeInt(mVertexWorkarounds); - stream.write(mUniforms.size()); - for (unsigned int i = 0; i < mUniforms.size(); ++i) + stream.writeInt(mVertexExecutables.size()); + for (size_t vertexExecutableIndex = 0; vertexExecutableIndex < mVertexExecutables.size(); vertexExecutableIndex++) { - stream.write(mUniforms[i]->type); - stream.write(mUniforms[i]->precision); - stream.write(mUniforms[i]->name); - stream.write(mUniforms[i]->arraySize); + VertexExecutable *vertexExecutable = mVertexExecutables[vertexExecutableIndex]; + + for (size_t inputIndex = 0; inputIndex < gl::MAX_VERTEX_ATTRIBS; inputIndex++) + { + const VertexFormat &vertexInput = vertexExecutable->inputs()[inputIndex]; + stream.writeInt(vertexInput.mType); + stream.writeInt(vertexInput.mNormalized); + stream.writeInt(vertexInput.mComponents); + stream.writeInt(vertexInput.mPureInteger); + } - stream.write(mUniforms[i]->psRegisterIndex); - stream.write(mUniforms[i]->vsRegisterIndex); - stream.write(mUniforms[i]->registerCount); + size_t vertexShaderSize = vertexExecutable->shaderExecutable()->getLength(); + stream.writeInt(vertexShaderSize); + + const uint8_t *vertexBlob = vertexExecutable->shaderExecutable()->getFunction(); + stream.writeBytes(vertexBlob, vertexShaderSize); } - stream.write(mUniformIndex.size()); - for (unsigned int i = 0; i < mUniformIndex.size(); ++i) + stream.writeString(mPixelHLSL); + stream.writeInt(mPixelWorkarounds); + stream.writeInt(mUsesFragDepth); + + stream.writeInt(mPixelShaderKey.size()); + for (size_t pixelShaderKeyIndex = 0; pixelShaderKeyIndex < mPixelShaderKey.size(); pixelShaderKeyIndex++) { - stream.write(mUniformIndex[i].name); - stream.write(mUniformIndex[i].element); - stream.write(mUniformIndex[i].index); + const PixelShaderOuputVariable &variable = mPixelShaderKey[pixelShaderKeyIndex]; + stream.writeInt(variable.type); + stream.writeString(variable.name); + stream.writeString(variable.source); + stream.writeInt(variable.outputIndex); } - UINT pixelShaderSize = mPixelExecutable->getLength(); - stream.write(pixelShaderSize); + stream.writeInt(mPixelExecutables.size()); + for (size_t pixelExecutableIndex = 0; pixelExecutableIndex < mPixelExecutables.size(); pixelExecutableIndex++) + { + PixelExecutable *pixelExecutable = mPixelExecutables[pixelExecutableIndex]; + + const std::vector outputs = pixelExecutable->outputSignature(); + stream.writeInt(outputs.size()); + for (size_t outputIndex = 0; outputIndex < outputs.size(); outputIndex++) + { + stream.writeInt(outputs[outputIndex]); + } + + size_t pixelShaderSize = pixelExecutable->shaderExecutable()->getLength(); + stream.writeInt(pixelShaderSize); + + const uint8_t *pixelBlob = pixelExecutable->shaderExecutable()->getFunction(); + stream.writeBytes(pixelBlob, pixelShaderSize); + } - UINT vertexShaderSize = mVertexExecutable->getLength(); - stream.write(vertexShaderSize); + size_t geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0; + stream.writeInt(geometryShaderSize); - UINT geometryShaderSize = (mGeometryExecutable != NULL) ? mGeometryExecutable->getLength() : 0; - stream.write(geometryShaderSize); + if (mGeometryExecutable != NULL && geometryShaderSize > 0) + { + const uint8_t *geometryBlob = mGeometryExecutable->getFunction(); + stream.writeBytes(geometryBlob, geometryShaderSize); + } -#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY) GUID identifier = mRenderer->getAdapterIdentifier(); -#endif GLsizei streamLength = stream.length(); const void *streamData = stream.data(); - GLsizei totalLength = streamLength + sizeof(GUID) + pixelShaderSize + vertexShaderSize + geometryShaderSize; + GLsizei totalLength = streamLength + sizeof(GUID); if (totalLength > bufSize) { if (length) @@ -1896,22 +1566,8 @@ bool ProgramBinary::save(void* binary, GLsizei bufSize, GLsizei *length) memcpy(ptr, streamData, streamLength); ptr += streamLength; -#if !defined(ANGLE_ENABLE_UNIVERSAL_BINARY) memcpy(ptr, &identifier, sizeof(GUID)); ptr += sizeof(GUID); -#endif - - memcpy(ptr, mPixelExecutable->getFunction(), pixelShaderSize); - ptr += pixelShaderSize; - - memcpy(ptr, mVertexExecutable->getFunction(), vertexShaderSize); - ptr += vertexShaderSize; - - if (mGeometryExecutable != NULL && geometryShaderSize > 0) - { - memcpy(ptr, mGeometryExecutable->getFunction(), geometryShaderSize); - ptr += geometryShaderSize; - } ASSERT(ptr - totalLength == binary); } @@ -1937,7 +1593,8 @@ GLint ProgramBinary::getLength() } } -bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader) +bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader, + const std::vector& transformFeedbackVaryings, GLenum transformFeedbackBufferMode) { if (!fragmentShader || !fragmentShader->isCompiled()) { @@ -1949,19 +1606,37 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin return false; } - std::string pixelHLSL = fragmentShader->getHLSL(); - std::string vertexHLSL = vertexShader->getHLSL(); + reset(); + + mTransformFeedbackBufferMode = transformFeedbackBufferMode; + + mShaderVersion = vertexShader->getShaderVersion(); + + mPixelHLSL = fragmentShader->getHLSL(); + mPixelWorkarounds = fragmentShader->getD3DWorkarounds(); + + mVertexHLSL = vertexShader->getHLSL(); + mVertexWorkarounds = vertexShader->getD3DWorkarounds(); // Map the varyings to the register file - const Varying *packing[IMPLEMENTATION_MAX_VARYING_VECTORS][4] = {NULL}; - int registers = packVaryings(infoLog, packing, fragmentShader); + VaryingPacking packing = { NULL }; + int registers = mDynamicHLSL->packVaryings(infoLog, packing, fragmentShader, vertexShader, transformFeedbackVaryings); if (registers < 0) { return false; } - if (!linkVaryings(infoLog, registers, packing, pixelHLSL, vertexHLSL, fragmentShader, vertexShader)) + if (!linkVaryings(infoLog, fragmentShader, vertexShader)) + { + return false; + } + + mUsesPointSize = vertexShader->usesPointSize(); + std::vector linkedVaryings; + if (!mDynamicHLSL->generateShaderLinkHLSL(infoLog, registers, packing, mPixelHLSL, mVertexHLSL, + fragmentShader, vertexShader, transformFeedbackVaryings, + &linkedVaryings, &mOutputVariables, &mPixelShaderKey, &mUsesFragDepth)) { return false; } @@ -1973,41 +1648,59 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin success = false; } - if (!linkUniforms(infoLog, vertexShader->getUniforms(), fragmentShader->getUniforms())) + if (!linkUniforms(infoLog, *vertexShader, *fragmentShader)) { success = false; } // special case for gl_DepthRange, the only built-in uniform (also a struct) - if (vertexShader->mUsesDepthRange || fragmentShader->mUsesDepthRange) + if (vertexShader->usesDepthRange() || fragmentShader->usesDepthRange()) + { + const sh::BlockMemberInfo &defaultInfo = sh::BlockMemberInfo::getDefaultBlockInfo(); + + mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0, -1, defaultInfo)); + mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0, -1, defaultInfo)); + mUniforms.push_back(new LinkedUniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0, -1, defaultInfo)); + } + + if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader)) { - mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.near", 0)); - mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.far", 0)); - mUniforms.push_back(new Uniform(GL_FLOAT, GL_HIGH_FLOAT, "gl_DepthRange.diff", 0)); + success = false; + } + + if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings, + transformFeedbackBufferMode, &mTransformFeedbackLinkedVaryings)) + { + success = false; } if (success) { - mVertexExecutable = mRenderer->compileToExecutable(infoLog, vertexHLSL.c_str(), rx::SHADER_VERTEX, DiscardWorkaround(vertexShader->mUsesDiscardRewriting)); - mPixelExecutable = mRenderer->compileToExecutable(infoLog, pixelHLSL.c_str(), rx::SHADER_PIXEL, DiscardWorkaround(fragmentShader->mUsesDiscardRewriting)); + VertexFormat defaultInputLayout[MAX_VERTEX_ATTRIBS]; + GetInputLayoutFromShader(vertexShader->activeAttributes(), 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; + } + rx::ShaderExecutable *defaultPixelExecutable = getPixelExecutableForOutputLayout(defaultPixelOutput); if (usesGeometryShader()) { - std::string geometryHLSL = generateGeometryShaderHLSL(registers, packing, fragmentShader, vertexShader); - mGeometryExecutable = mRenderer->compileToExecutable(infoLog, geometryHLSL.c_str(), rx::SHADER_GEOMETRY, rx::ANGLE_D3D_WORKAROUND_NONE); + 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); } - if (!mVertexExecutable || !mPixelExecutable || (usesGeometryShader() && !mGeometryExecutable)) + if (!defaultVertexExecutable || !defaultPixelExecutable || (usesGeometryShader() && !mGeometryExecutable)) { infoLog.append("Failed to create D3D shaders."); success = false; - - delete mVertexExecutable; - mVertexExecutable = NULL; - delete mPixelExecutable; - mPixelExecutable = NULL; - delete mGeometryExecutable; - mGeometryExecutable = NULL; + reset(); } } @@ -2018,88 +1711,363 @@ bool ProgramBinary::link(InfoLog &infoLog, const AttributeBindings &attributeBin bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader) { unsigned int usedLocations = 0; + const std::vector &activeAttributes = vertexShader->activeAttributes(); // Link attributes that have a binding location - for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++) + for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++) { - int location = attributeBindings.getAttributeBinding(attribute->name); - - if (location != -1) // Set by glBindAttribLocation - { - if (!mLinkedAttribute[location].name.empty()) - { - // Multiple active attributes bound to the same location; not an error - } + const sh::Attribute &attribute = activeAttributes[attributeIndex]; + const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; - mLinkedAttribute[location] = *attribute; + mShaderAttributes[attributeIndex] = attribute; - int rows = VariableRowCount(attribute->type); + if (location != -1) // Set by glBindAttribLocation or by location layout qualifier + { + const int rows = VariableRegisterCount(attribute.type); if (rows + location > MAX_VERTEX_ATTRIBS) { - infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute->name.c_str(), location); + infoLog.append("Active attribute (%s) at location %d is too big to fit", attribute.name.c_str(), location); return false; } - for (int i = 0; i < rows; i++) + for (int row = 0; row < rows; row++) { - usedLocations |= 1 << (location + i); + const int rowLocation = location + row; + sh::ShaderVariable &linkedAttribute = mLinkedAttribute[rowLocation]; + + // In GLSL 3.00, attribute aliasing produces a link error + // In GLSL 1.00, attribute aliasing is allowed + if (mShaderVersion >= 300) + { + if (!linkedAttribute.name.empty()) + { + infoLog.append("Attribute '%s' aliases attribute '%s' at location %d", attribute.name.c_str(), linkedAttribute.name.c_str(), rowLocation); + return false; + } + } + + linkedAttribute = attribute; + usedLocations |= 1 << rowLocation; } } } // Link attributes that don't have a binding location - for (AttributeArray::iterator attribute = vertexShader->mAttributes.begin(); attribute != vertexShader->mAttributes.end(); attribute++) + for (unsigned int attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++) { - int location = attributeBindings.getAttributeBinding(attribute->name); + const sh::Attribute &attribute = activeAttributes[attributeIndex]; + const int location = attribute.location == -1 ? attributeBindings.getAttributeBinding(attribute.name) : attribute.location; - if (location == -1) // Not set by glBindAttribLocation + if (location == -1) // Not set by glBindAttribLocation or by location layout qualifier { - int rows = VariableRowCount(attribute->type); + int rows = VariableRegisterCount(attribute.type); int availableIndex = AllocateFirstFreeBits(&usedLocations, rows, MAX_VERTEX_ATTRIBS); if (availableIndex == -1 || availableIndex + rows > MAX_VERTEX_ATTRIBS) { - infoLog.append("Too many active attributes (%s)", attribute->name.c_str()); + infoLog.append("Too many active attributes (%s)", attribute.name.c_str()); return false; // Fail to link } - mLinkedAttribute[availableIndex] = *attribute; + mLinkedAttribute[availableIndex] = attribute; } } for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; ) { int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name); - int rows = std::max(VariableRowCount(mLinkedAttribute[attributeIndex].type), 1); + int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type); for (int r = 0; r < rows; r++) { - mSemanticIndex[attributeIndex++] = index++; + mSemanticIndex[attributeIndex++] = index++; + } + } + + initAttributesByLayout(); + + return true; +} + +bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable, + const sh::ShaderVariable &fragmentVariable, bool validatePrecision) +{ + if (vertexVariable.type != fragmentVariable.type) + { + infoLog.append("Types for %s differ between vertex and fragment shaders", variableName.c_str()); + return false; + } + if (vertexVariable.arraySize != fragmentVariable.arraySize) + { + infoLog.append("Array sizes for %s differ between vertex and fragment shaders", variableName.c_str()); + return false; + } + if (validatePrecision && vertexVariable.precision != fragmentVariable.precision) + { + infoLog.append("Precisions for %s differ between vertex and fragment shaders", variableName.c_str()); + return false; + } + + 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()) + { + infoLog.append("Structure lengths for %s differ between vertex and fragment shaders", varName.c_str()); + return false; + } + const unsigned int numMembers = vertexVar.fields.size(); + for (unsigned int memberIndex = 0; memberIndex < numMembers; memberIndex++) + { + const ShaderVarType &vertexMember = vertexVar.fields[memberIndex]; + const ShaderVarType &fragmentMember = fragmentVar.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()); + return false; + } + + const std::string memberName = varName.substr(0, varName.length()-1) + "." + vertexVar.name + "'"; + if (!linkValidateVariables(infoLog, memberName, vertexMember, fragmentMember)) + { + return false; + } + } + + return true; +} + +bool ProgramBinary::linkValidateVariables(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) +{ + if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false)) + { + return false; + } + + if (vertexVarying.interpolation != fragmentVarying.interpolation) + { + infoLog.append("Interpolation types for %s differ between vertex and fragment shaders", varyingName.c_str()); + return false; + } + + 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) +{ + if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true)) + { + return false; + } + + if (vertexUniform.isRowMajorMatrix != fragmentUniform.isRowMajorMatrix) + { + 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) +{ + const std::vector &vertexUniforms = vertexShader.getUniforms(); + const std::vector &fragmentUniforms = fragmentShader.getUniforms(); + + // Check that uniforms defined in the vertex and fragment shaders are identical + typedef std::map UniformMap; + UniformMap linkedUniforms; + + for (unsigned int vertexUniformIndex = 0; vertexUniformIndex < vertexUniforms.size(); vertexUniformIndex++) + { + const sh::Uniform &vertexUniform = vertexUniforms[vertexUniformIndex]; + linkedUniforms[vertexUniform.name] = &vertexUniform; + } + + for (unsigned int fragmentUniformIndex = 0; fragmentUniformIndex < fragmentUniforms.size(); fragmentUniformIndex++) + { + const sh::Uniform &fragmentUniform = fragmentUniforms[fragmentUniformIndex]; + UniformMap::const_iterator entry = linkedUniforms.find(fragmentUniform.name); + if (entry != linkedUniforms.end()) + { + const sh::Uniform &vertexUniform = *entry->second; + const std::string &uniformName = "uniform '" + vertexUniform.name + "'"; + if (!linkValidateVariables(infoLog, uniformName, vertexUniform, fragmentUniform)) + { + return false; + } + } + } + + for (unsigned int uniformIndex = 0; uniformIndex < vertexUniforms.size(); uniformIndex++) + { + const sh::Uniform &uniform = vertexUniforms[uniformIndex]; + defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShader.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 (!indexUniforms(infoLog)) + { + return false; + } + + initializeUniformStorage(); + + return true; +} + +void ProgramBinary::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister) +{ + ShShaderOutput outputType = Shader::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, + const std::string &fullName, sh::HLSLBlockEncoder *encoder) +{ + if (uniform.isStruct()) + { + for (unsigned int elementIndex = 0; elementIndex < uniform.elementCount(); elementIndex++) + { + const std::string &elementString = (uniform.isArray() ? ArrayString(elementIndex) : ""); + + encoder->enterAggregateType(); + + for (size_t fieldIndex = 0; fieldIndex < uniform.fields.size(); fieldIndex++) + { + const sh::Uniform &field = uniform.fields[fieldIndex]; + const std::string &fieldFullName = (fullName + elementString + "." + field.name); + + defineUniform(shader, field, fieldFullName, encoder); + } + + encoder->exitAggregateType(); + } + } + else // Not a struct + { + // Arrays are treated as aggregate types + if (uniform.isArray()) + { + encoder->enterAggregateType(); + } + + LinkedUniform *linkedUniform = getUniformByName(fullName); + + if (!linkedUniform) + { + linkedUniform = new LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize, + -1, sh::BlockMemberInfo::getDefaultBlockInfo()); + ASSERT(linkedUniform); + linkedUniform->registerElement = encoder->getCurrentElement(); + mUniforms.push_back(linkedUniform); + } + + ASSERT(linkedUniform->registerElement == encoder->getCurrentElement()); + + if (shader == GL_FRAGMENT_SHADER) + { + linkedUniform->psRegisterIndex = encoder->getCurrentRegister(); + } + else if (shader == GL_VERTEX_SHADER) + { + linkedUniform->vsRegisterIndex = encoder->getCurrentRegister(); } - } + else UNREACHABLE(); - initAttributesByLayout(); + // Advance the uniform offset, to track registers allocation for structs + encoder->encodeType(uniform.type, uniform.arraySize, false); - return true; + // Arrays are treated as aggregate types + if (uniform.isArray()) + { + encoder->exitAggregateType(); + } + } } -bool ProgramBinary::linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &vertexUniforms, const sh::ActiveUniforms &fragmentUniforms) +bool ProgramBinary::indexSamplerUniform(const LinkedUniform &uniform, InfoLog &infoLog) { - for (sh::ActiveUniforms::const_iterator uniform = vertexUniforms.begin(); uniform != vertexUniforms.end(); uniform++) + ASSERT(IsSampler(uniform.type)); + ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX); + + if (uniform.vsRegisterIndex != GL_INVALID_INDEX) { - if (!defineUniform(GL_VERTEX_SHADER, *uniform, infoLog)) + if (!assignSamplers(uniform.vsRegisterIndex, uniform.type, uniform.arraySize, mSamplersVS, + &mUsedVertexSamplerRange, mRenderer->getMaxVertexTextureImageUnits())) + { + infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", + mRenderer->getMaxVertexTextureImageUnits()); + return false; + } + + unsigned int maxVertexVectors = mRenderer->getReservedVertexUniformVectors() + + mRenderer->getMaxVertexUniformVectors(); + if (uniform.vsRegisterIndex + uniform.registerCount > maxVertexVectors) { + infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", + mRenderer->getMaxVertexUniformVectors()); return false; } } - for (sh::ActiveUniforms::const_iterator uniform = fragmentUniforms.begin(); uniform != fragmentUniforms.end(); uniform++) + if (uniform.psRegisterIndex != GL_INVALID_INDEX) { - if (!defineUniform(GL_FRAGMENT_SHADER, *uniform, infoLog)) + if (!assignSamplers(uniform.psRegisterIndex, uniform.type, uniform.arraySize, mSamplersPS, + &mUsedPixelSamplerRange, MAX_TEXTURE_IMAGE_UNITS)) + { + infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", + MAX_TEXTURE_IMAGE_UNITS); + return false; + } + + unsigned int maxFragmentVectors = mRenderer->getReservedFragmentUniformVectors() + + mRenderer->getMaxFragmentUniformVectors(); + if (uniform.psRegisterIndex + uniform.registerCount > maxFragmentVectors) { + infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", + mRenderer->getMaxFragmentUniformVectors()); return false; } } @@ -2107,274 +2075,341 @@ bool ProgramBinary::linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &ver return true; } -bool ProgramBinary::defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog) +bool ProgramBinary::indexUniforms(InfoLog &infoLog) { - if (constant.type == GL_SAMPLER_2D || - constant.type == GL_SAMPLER_CUBE) + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) { - unsigned int samplerIndex = constant.registerIndex; - - do + const LinkedUniform &uniform = *mUniforms[uniformIndex]; + + if (IsSampler(uniform.type)) { - if (shader == GL_VERTEX_SHADER) - { - if (samplerIndex < mRenderer->getMaxVertexTextureImageUnits()) - { - mSamplersVS[samplerIndex].active = true; - mSamplersVS[samplerIndex].textureType = (constant.type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D; - mSamplersVS[samplerIndex].logicalTextureUnit = 0; - mUsedVertexSamplerRange = std::max(samplerIndex + 1, mUsedVertexSamplerRange); - } - else - { - infoLog.append("Vertex shader sampler count exceeds the maximum vertex texture units (%d).", mRenderer->getMaxVertexTextureImageUnits()); - return false; - } - } - else if (shader == GL_FRAGMENT_SHADER) + if (!indexSamplerUniform(uniform, infoLog)) { - if (samplerIndex < MAX_TEXTURE_IMAGE_UNITS) - { - mSamplersPS[samplerIndex].active = true; - mSamplersPS[samplerIndex].textureType = (constant.type == GL_SAMPLER_CUBE) ? TEXTURE_CUBE : TEXTURE_2D; - mSamplersPS[samplerIndex].logicalTextureUnit = 0; - mUsedPixelSamplerRange = std::max(samplerIndex + 1, mUsedPixelSamplerRange); - } - else - { - infoLog.append("Pixel shader sampler count exceeds MAX_TEXTURE_IMAGE_UNITS (%d).", MAX_TEXTURE_IMAGE_UNITS); - return false; - } + return false; } - else UNREACHABLE(); + } - samplerIndex++; + for (unsigned int arrayElementIndex = 0; arrayElementIndex < uniform.elementCount(); arrayElementIndex++) + { + mUniformIndex.push_back(VariableLocation(uniform.name, arrayElementIndex, uniformIndex)); } - while (samplerIndex < constant.registerIndex + constant.arraySize); } - Uniform *uniform = NULL; - GLint location = getUniformLocation(constant.name); + return true; +} - if (location >= 0) // Previously defined, type and precision must match - { - uniform = mUniforms[mUniformIndex[location].index]; +bool ProgramBinary::assignSamplers(unsigned int startSamplerIndex, + GLenum samplerType, + unsigned int samplerCount, + Sampler *outArray, + GLuint *usedRange, + unsigned int limit) +{ + unsigned int samplerIndex = startSamplerIndex; - if (uniform->type != constant.type) + do + { + if (samplerIndex < limit) { - infoLog.append("Types for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str()); - return false; + outArray[samplerIndex].active = true; + outArray[samplerIndex].textureType = GetTextureType(samplerType); + outArray[samplerIndex].logicalTextureUnit = 0; + *usedRange = std::max(samplerIndex + 1, *usedRange); } - - if (uniform->precision != constant.precision) + else { - infoLog.append("Precisions for uniform %s do not match between the vertex and fragment shader", uniform->name.c_str()); return false; } - } - else + + samplerIndex++; + } while (samplerIndex < startSamplerIndex + samplerCount); + + return true; +} + +bool ProgramBinary::areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock) +{ + const char* blockName = vertexInterfaceBlock.name.c_str(); + + // validate blocks for the same member types + if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size()) { - uniform = new Uniform(constant.type, constant.precision, constant.name, constant.arraySize); + infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName); + return false; } - if (!uniform) + if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize) { + infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName); return false; } - if (shader == GL_FRAGMENT_SHADER) + if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout) { - uniform->psRegisterIndex = constant.registerIndex; + infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName); + return false; } - else if (shader == GL_VERTEX_SHADER) + + const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size(); + for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++) { - uniform->vsRegisterIndex = constant.registerIndex; + const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex]; + const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex]; + + if (vertexMember.name != fragmentMember.name) + { + infoLog.append("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')", + blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str()); + return false; + } + + std::string uniformName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'"; + if (!linkValidateVariables(infoLog, uniformName, vertexMember, fragmentMember)) + { + return false; + } } - else UNREACHABLE(); - if (location >= 0) + return true; +} + +bool ProgramBinary::linkUniformBlocks(InfoLog &infoLog, const VertexShader &vertexShader, + const FragmentShader &fragmentShader) +{ + const std::vector &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks(); + const std::vector &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks(); + + // Check that interface blocks defined in the vertex and fragment shaders are identical + typedef std::map UniformBlockMap; + UniformBlockMap linkedUniformBlocks; + + for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) { - return uniform->type == constant.type; + const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex]; + linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock; } - mUniforms.push_back(uniform); - unsigned int uniformIndex = mUniforms.size() - 1; - - for (unsigned int i = 0; i < uniform->elementCount(); i++) + for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) { - mUniformIndex.push_back(UniformLocation(constant.name, i, uniformIndex)); + const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex]; + UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name); + if (entry != linkedUniformBlocks.end()) + { + const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second; + if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock)) + { + return false; + } + } } - if (shader == GL_VERTEX_SHADER) + for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++) { - if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedVertexUniformVectors() + mRenderer->getMaxVertexUniformVectors()) + if (!defineUniformBlock(infoLog, vertexShader, vertexInterfaceBlocks[blockIndex])) { - infoLog.append("Vertex shader active uniforms exceed GL_MAX_VERTEX_UNIFORM_VECTORS (%u)", mRenderer->getMaxVertexUniformVectors()); return false; } } - else if (shader == GL_FRAGMENT_SHADER) + + for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++) { - if (constant.registerIndex + uniform->registerCount > mRenderer->getReservedFragmentUniformVectors() + mRenderer->getMaxFragmentUniformVectors()) + if (!defineUniformBlock(infoLog, fragmentShader, fragmentInterfaceBlocks[blockIndex])) { - infoLog.append("Fragment shader active uniforms exceed GL_MAX_FRAGMENT_UNIFORM_VECTORS (%u)", mRenderer->getMaxFragmentUniformVectors()); return false; } } - else UNREACHABLE(); return true; } -std::string ProgramBinary::generateGeometryShaderHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const -{ - // for now we only handle point sprite emulation - ASSERT(usesPointSpriteEmulation()); - return generatePointSpriteHLSL(registers, packing, fragmentShader, vertexShader); -} - -std::string ProgramBinary::generatePointSpriteHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const +bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector &linkedVaryings, + const std::vector &transformFeedbackVaryingNames, + GLenum transformFeedbackBufferMode, + std::vector *outTransformFeedbackLinkedVaryings) const { - ASSERT(registers >= 0); - ASSERT(vertexShader->mUsesPointSize); - ASSERT(mRenderer->getMajorShaderModel() >= 4); + size_t totalComponents = 0; + const size_t maxSeparateComponents = mRenderer->getMaxTransformFeedbackSeparateComponents(); + const size_t maxInterleavedComponents = mRenderer->getMaxTransformFeedbackInterleavedComponents(); - std::string geomHLSL; + // Gather the linked varyings that are used for transform feedback, they should all exist. + outTransformFeedbackLinkedVaryings->clear(); + for (size_t i = 0; i < transformFeedbackVaryingNames.size(); i++) + { + bool found = false; + for (size_t j = 0; j < linkedVaryings.size(); j++) + { + if (transformFeedbackVaryingNames[i] == linkedVaryings[j].name) + { + for (size_t k = 0; k < outTransformFeedbackLinkedVaryings->size(); k++) + { + if (outTransformFeedbackLinkedVaryings->at(k).name == linkedVaryings[j].name) + { + infoLog.append("Two transform feedback varyings specify the same output variable (%s).", linkedVaryings[j].name.c_str()); + return false; + } + } - std::string varyingSemantic = "TEXCOORD"; + size_t componentCount = linkedVaryings[j].semanticIndexCount * 4; + if (transformFeedbackBufferMode == GL_SEPARATE_ATTRIBS && + componentCount > maxSeparateComponents) + { + infoLog.append("Transform feedback varying's %s components (%u) exceed the maximum separate components (%u).", + linkedVaryings[j].name.c_str(), componentCount, maxSeparateComponents); + return false; + } - std::string fragCoordSemantic; - std::string pointCoordSemantic; + totalComponents += componentCount; - int reservedRegisterIndex = registers; + outTransformFeedbackLinkedVaryings->push_back(linkedVaryings[j]); + found = true; + break; + } + } - if (fragmentShader->mUsesFragCoord) - { - fragCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); + // All transform feedback varyings are expected to exist since packVaryings checks for them. + ASSERT(found); } - if (fragmentShader->mUsesPointCoord) + if (transformFeedbackBufferMode == GL_INTERLEAVED_ATTRIBS && totalComponents > maxInterleavedComponents) { - pointCoordSemantic = varyingSemantic + str(reservedRegisterIndex++); + infoLog.append("Transform feedback varying total components (%u) exceed the maximum interleaved components (%u).", + totalComponents, maxInterleavedComponents); + return false; } - geomHLSL += "uniform float4 dx_ViewCoords : register(c1);\n" - "\n" - "struct GS_INPUT\n" - "{\n"; + return true; +} - for (int r = 0; r < registers; r++) +void ProgramBinary::defineUniformBlockMembers(const std::vector &fields, const std::string &prefix, int blockIndex, + sh::BlockLayoutEncoder *encoder, std::vector *blockUniformIndexes) +{ + for (unsigned int uniformIndex = 0; uniformIndex < fields.size(); uniformIndex++) { - int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1)); + const sh::InterfaceBlockField &field = fields[uniformIndex]; + const std::string &fieldName = (prefix.empty() ? field.name : prefix + "." + field.name); - geomHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n"; - } + if (field.isStruct()) + { + for (unsigned int arrayElement = 0; arrayElement < field.elementCount(); arrayElement++) + { + encoder->enterAggregateType(); - if (fragmentShader->mUsesFragCoord) - { - geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; - } + const std::string uniformElementName = fieldName + (field.isArray() ? ArrayString(arrayElement) : ""); + defineUniformBlockMembers(field.fields, uniformElementName, blockIndex, encoder, blockUniformIndexes); - geomHLSL += " float gl_PointSize : PSIZE;\n" - " float4 gl_Position : SV_Position;\n" - "};\n" - "\n" - "struct GS_OUTPUT\n" - "{\n"; + encoder->exitAggregateType(); + } + } + else + { + sh::BlockMemberInfo memberInfo = encoder->encodeInterfaceBlockField(field); - for (int r = 0; r < registers; r++) - { - int registerSize = packing[r][3] ? 4 : (packing[r][2] ? 3 : (packing[r][1] ? 2 : 1)); + LinkedUniform *newUniform = new LinkedUniform(field.type, field.precision, fieldName, field.arraySize, + blockIndex, memberInfo); - geomHLSL += " float" + str(registerSize) + " v" + str(r) + " : " + varyingSemantic + str(r) + ";\n"; + // add to uniform list, but not index, since uniform block uniforms have no location + blockUniformIndexes->push_back(mUniforms.size()); + mUniforms.push_back(newUniform); + } } +} - if (fragmentShader->mUsesFragCoord) +bool ProgramBinary::defineUniformBlock(InfoLog &infoLog, const Shader &shader, const sh::InterfaceBlock &interfaceBlock) +{ + // create uniform block entries if they do not exist + if (getUniformBlockIndex(interfaceBlock.name) == GL_INVALID_INDEX) { - geomHLSL += " float4 gl_FragCoord : " + fragCoordSemantic + ";\n"; - } + std::vector blockUniformIndexes; + const unsigned int blockIndex = mUniformBlocks.size(); - if (fragmentShader->mUsesPointCoord) - { - geomHLSL += " float2 gl_PointCoord : " + pointCoordSemantic + ";\n"; - } + // define member uniforms + sh::BlockLayoutEncoder *encoder = NULL; + + if (interfaceBlock.layout == sh::BLOCKLAYOUT_STANDARD) + { + encoder = new sh::Std140BlockEncoder; + } + else + { + encoder = new sh::HLSLBlockEncoder(sh::HLSLBlockEncoder::ENCODE_PACKED); + } + ASSERT(encoder); - geomHLSL += " float gl_PointSize : PSIZE;\n" - " float4 gl_Position : SV_Position;\n" - "};\n" - "\n" - "static float2 pointSpriteCorners[] = \n" - "{\n" - " float2( 0.5f, -0.5f),\n" - " float2( 0.5f, 0.5f),\n" - " float2(-0.5f, -0.5f),\n" - " float2(-0.5f, 0.5f)\n" - "};\n" - "\n" - "static float2 pointSpriteTexcoords[] = \n" - "{\n" - " float2(1.0f, 1.0f),\n" - " float2(1.0f, 0.0f),\n" - " float2(0.0f, 1.0f),\n" - " float2(0.0f, 0.0f)\n" - "};\n" - "\n" - "static float minPointSize = " + str(ALIASED_POINT_SIZE_RANGE_MIN) + ".0f;\n" - "static float maxPointSize = " + str(mRenderer->getMaxPointSize()) + ".0f;\n" - "\n" - "[maxvertexcount(4)]\n" - "void main(point GS_INPUT input[1], inout TriangleStream outStream)\n" - "{\n" - " GS_OUTPUT output = (GS_OUTPUT)0;\n" - " output.gl_PointSize = input[0].gl_PointSize;\n"; + defineUniformBlockMembers(interfaceBlock.fields, "", blockIndex, encoder, &blockUniformIndexes); - for (int r = 0; r < registers; r++) - { - geomHLSL += " output.v" + str(r) + " = input[0].v" + str(r) + ";\n"; - } + size_t dataSize = encoder->getBlockSize(); - if (fragmentShader->mUsesFragCoord) - { - geomHLSL += " output.gl_FragCoord = input[0].gl_FragCoord;\n"; + // create all the uniform blocks + if (interfaceBlock.arraySize > 0) + { + for (unsigned int uniformBlockElement = 0; uniformBlockElement < interfaceBlock.arraySize; uniformBlockElement++) + { + UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, uniformBlockElement, dataSize); + newUniformBlock->memberUniformIndexes = blockUniformIndexes; + mUniformBlocks.push_back(newUniformBlock); + } + } + else + { + UniformBlock *newUniformBlock = new UniformBlock(interfaceBlock.name, GL_INVALID_INDEX, dataSize); + newUniformBlock->memberUniformIndexes = blockUniformIndexes; + mUniformBlocks.push_back(newUniformBlock); + } } - geomHLSL += " \n" - " float gl_PointSize = clamp(input[0].gl_PointSize, minPointSize, maxPointSize);\n" - " float4 gl_Position = input[0].gl_Position;\n" - " float2 viewportScale = float2(1.0f / dx_ViewCoords.x, 1.0f / dx_ViewCoords.y) * gl_Position.w;\n"; + // 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 (int corner = 0; corner < 4; corner++) + for (unsigned int uniformBlockElement = 0; uniformBlockElement < elementCount; uniformBlockElement++) { - geomHLSL += " \n" - " output.gl_Position = gl_Position + float4(pointSpriteCorners[" + str(corner) + "] * viewportScale * gl_PointSize, 0.0f, 0.0f);\n"; + UniformBlock *uniformBlock = mUniformBlocks[blockIndex + uniformBlockElement]; + ASSERT(uniformBlock->name == interfaceBlock.name); - if (fragmentShader->mUsesPointCoord) + if (!assignUniformBlockRegister(infoLog, uniformBlock, shader.getType(), + interfaceBlockRegister + uniformBlockElement)) { - geomHLSL += " output.gl_PointCoord = pointSpriteTexcoords[" + str(corner) + "];\n"; + return false; } - - geomHLSL += " outStream.Append(output);\n"; } - geomHLSL += " \n" - " outStream.RestartStrip();\n" - "}\n"; - - return geomHLSL; + return true; } -// This method needs to match OutputHLSL::decorate -std::string ProgramBinary::decorateAttribute(const std::string &name) +bool ProgramBinary::assignUniformBlockRegister(InfoLog &infoLog, UniformBlock *uniformBlock, GLenum shader, unsigned int registerIndex) { - if (name.compare(0, 3, "gl_") != 0 && name.compare(0, 3, "dx_") != 0) + if (shader == GL_VERTEX_SHADER) + { + uniformBlock->vsRegisterIndex = registerIndex; + unsigned int maximumBlocks = mRenderer->getMaxVertexShaderUniformBuffers(); + + if (registerIndex - mRenderer->getReservedVertexUniformBuffers() >= maximumBlocks) + { + infoLog.append("Vertex shader uniform block count exceed GL_MAX_VERTEX_UNIFORM_BLOCKS (%u)", maximumBlocks); + return false; + } + } + else if (shader == GL_FRAGMENT_SHADER) { - return "_" + name; + uniformBlock->psRegisterIndex = registerIndex; + unsigned int maximumBlocks = mRenderer->getMaxFragmentShaderUniformBuffers(); + + if (registerIndex - mRenderer->getReservedFragmentUniformBuffers() >= maximumBlocks) + { + infoLog.append("Fragment shader uniform block count exceed GL_MAX_FRAGMENT_UNIFORM_BLOCKS (%u)", maximumBlocks); + return false; + } } - - return name; + else UNREACHABLE(); + + return true; } -bool ProgramBinary::isValidated() const +bool ProgramBinary::isValidated() const { return mValidated; } @@ -2500,6 +2535,141 @@ GLint ProgramBinary::getActiveUniformMaxLength() const return maxLength; } +GLint ProgramBinary::getActiveUniformi(GLuint index, GLenum pname) const +{ + const gl::LinkedUniform& uniform = *mUniforms[index]; + + switch (pname) + { + case GL_UNIFORM_TYPE: return static_cast(uniform.type); + case GL_UNIFORM_SIZE: return static_cast(uniform.elementCount()); + case GL_UNIFORM_NAME_LENGTH: return static_cast(uniform.name.size() + 1 + (uniform.isArray() ? 3 : 0)); + case GL_UNIFORM_BLOCK_INDEX: return uniform.blockIndex; + + case GL_UNIFORM_OFFSET: return uniform.blockInfo.offset; + case GL_UNIFORM_ARRAY_STRIDE: return uniform.blockInfo.arrayStride; + case GL_UNIFORM_MATRIX_STRIDE: return uniform.blockInfo.matrixStride; + case GL_UNIFORM_IS_ROW_MAJOR: return static_cast(uniform.blockInfo.isRowMajorMatrix); + + default: + UNREACHABLE(); + break; + } + return 0; +} + +bool ProgramBinary::isValidUniformLocation(GLint location) const +{ + ASSERT(rx::IsIntegerCastSafe(mUniformIndex.size())); + return (location >= 0 && location < static_cast(mUniformIndex.size())); +} + +LinkedUniform *ProgramBinary::getUniformByLocation(GLint location) const +{ + ASSERT(location >= 0 && static_cast(location) < mUniformIndex.size()); + return mUniforms[mUniformIndex[location].index]; +} + +LinkedUniform *ProgramBinary::getUniformByName(const std::string &name) const +{ + for (size_t uniformIndex = 0; uniformIndex < mUniforms.size(); uniformIndex++) + { + if (mUniforms[uniformIndex]->name == name) + { + return mUniforms[uniformIndex]; + } + } + + return NULL; +} + +void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const +{ + ASSERT(uniformBlockIndex < mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount() + + const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex]; + + if (bufSize > 0) + { + std::string string = uniformBlock.name; + + if (uniformBlock.isArrayElement()) + { + string += ArrayString(uniformBlock.elementIndex); + } + + strncpy(uniformBlockName, string.c_str(), bufSize); + uniformBlockName[bufSize - 1] = '\0'; + + if (length) + { + *length = strlen(uniformBlockName); + } + } +} + +void ProgramBinary::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const +{ + ASSERT(uniformBlockIndex < mUniformBlocks.size()); // index must be smaller than getActiveUniformBlockCount() + + const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex]; + + switch (pname) + { + case GL_UNIFORM_BLOCK_DATA_SIZE: + *params = static_cast(uniformBlock.dataSize); + break; + case GL_UNIFORM_BLOCK_NAME_LENGTH: + *params = static_cast(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0)); + break; + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: + *params = static_cast(uniformBlock.memberUniformIndexes.size()); + break; + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: + { + for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++) + { + params[blockMemberIndex] = static_cast(uniformBlock.memberUniformIndexes[blockMemberIndex]); + } + } + break; + case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: + *params = static_cast(uniformBlock.isReferencedByVertexShader()); + break; + case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: + *params = static_cast(uniformBlock.isReferencedByFragmentShader()); + break; + default: UNREACHABLE(); + } +} + +GLuint ProgramBinary::getActiveUniformBlockCount() const +{ + return mUniformBlocks.size(); +} + +GLuint ProgramBinary::getActiveUniformBlockMaxLength() const +{ + unsigned int maxLength = 0; + + unsigned int numUniformBlocks = mUniformBlocks.size(); + for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++) + { + const UniformBlock &uniformBlock = *mUniformBlocks[uniformBlockIndex]; + if (!uniformBlock.name.empty()) + { + const unsigned int length = uniformBlock.name.length() + 1; + + // Counting in "[0]". + const unsigned int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0); + + maxLength = std::max(length + arrayLength, maxLength); + } + } + + return maxLength; +} + void ProgramBinary::validate(InfoLog &infoLog) { applyUniforms(); @@ -2518,6 +2688,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) // 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]; @@ -2532,7 +2703,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) if (mSamplersPS[i].active) { unsigned int unit = mSamplersPS[i].logicalTextureUnit; - + if (unit >= maxCombinedTextureImageUnits) { if (infoLog) @@ -2567,7 +2738,7 @@ bool ProgramBinary::validateSamplers(InfoLog *infoLog) if (mSamplersVS[i].active) { unsigned int unit = mSamplersVS[i].logicalTextureUnit; - + if (unit >= maxCombinedTextureImageUnits) { if (infoLog) @@ -2648,4 +2819,71 @@ 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); + + 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(); + } + mUsedVertexSamplerRange = 0; + mUsedPixelSamplerRange = 0; + mUsesPointSize = false; + mShaderVersion = 0; + mDirtySamplerMapping = true; + + SafeDeleteContainer(mUniforms); + SafeDeleteContainer(mUniformBlocks); + mUniformIndex.clear(); + mOutputVariables.clear(); + SafeDelete(mVertexUniformStorage); + SafeDelete(mFragmentUniformStorage); + + mValidated = false; +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h index d6320863f2..f0fc431021 100644 --- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h +++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.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. // @@ -10,25 +10,31 @@ #ifndef LIBGLESV2_PROGRAM_BINARY_H_ #define LIBGLESV2_PROGRAM_BINARY_H_ -#define GL_APICALL -#include -#include +#include "angle_gl.h" #include #include #include "common/RefCountObject.h" #include "angletypes.h" -#include "libGLESv2/mathutil.h" +#include "common/mathutil.h" #include "libGLESv2/Uniform.h" #include "libGLESv2/Shader.h" #include "libGLESv2/Constants.h" +#include "libGLESv2/renderer/d3d/VertexDataManager.h" +#include "libGLESv2/DynamicHLSL.h" + +namespace sh +{ +class HLSLBlockEncoder; +} namespace rx { class ShaderExecutable; class Renderer; struct TranslatedAttribute; +class UniformStorage; } namespace gl @@ -37,22 +43,41 @@ class FragmentShader; class VertexShader; class InfoLog; class AttributeBindings; -struct Varying; +class Buffer; +class Framebuffer; // Struct used for correlating uniforms/elements of uniform arrays to handles -struct UniformLocation +struct VariableLocation { - UniformLocation() + VariableLocation() { } - UniformLocation(const std::string &name, unsigned int element, unsigned int index); + VariableLocation(const std::string &name, unsigned int element, unsigned int index); std::string name; unsigned int element; unsigned int index; }; +struct LinkedVarying +{ + LinkedVarying(); + LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName, + unsigned int semanticIndex, unsigned int semanticIndexCount); + + // Original GL name + std::string name; + + GLenum type; + GLsizei size; + + // DirectX semantic information + std::string semanticName; + unsigned int semanticIndex; + unsigned int semanticIndexCount; +}; + // This is the result of linking a program. It is the state that would be passed to ProgramBinary. class ProgramBinary : public RefCountObject { @@ -60,9 +85,10 @@ class ProgramBinary : public RefCountObject explicit ProgramBinary(rx::Renderer *renderer); ~ProgramBinary(); - rx::ShaderExecutable *getPixelExecutable(); - rx::ShaderExecutable *getVertexExecutable(); - rx::ShaderExecutable *getGeometryExecutable(); + rx::ShaderExecutable *getPixelExecutableForFramebuffer(const Framebuffer *fbo); + rx::ShaderExecutable *getPixelExecutableForOutputLayout(const std::vector &outputLayout); + rx::ShaderExecutable *getVertexExecutableForInputLayout(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS]); + rx::ShaderExecutable *getGeometryExecutable() const; GLuint getAttributeLocation(const char *name); int getSemanticIndex(int attributeIndex); @@ -75,29 +101,44 @@ class ProgramBinary : public RefCountObject bool usesGeometryShader() const; GLint getUniformLocation(std::string name); - bool setUniform1fv(GLint location, GLsizei count, const GLfloat *v); - bool setUniform2fv(GLint location, GLsizei count, const GLfloat *v); - bool setUniform3fv(GLint location, GLsizei count, const GLfloat *v); - bool setUniform4fv(GLint location, GLsizei count, const GLfloat *v); - bool setUniformMatrix2fv(GLint location, GLsizei count, const GLfloat *value); - bool setUniformMatrix3fv(GLint location, GLsizei count, const GLfloat *value); - bool setUniformMatrix4fv(GLint location, GLsizei count, const GLfloat *value); - bool setUniform1iv(GLint location, GLsizei count, const GLint *v); - bool setUniform2iv(GLint location, GLsizei count, const GLint *v); - bool setUniform3iv(GLint location, GLsizei count, const GLint *v); - bool setUniform4iv(GLint location, GLsizei count, const GLint *v); + GLuint getUniformIndex(std::string name); + GLuint getUniformBlockIndex(std::string name); + void setUniform1fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform2fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform3fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform4fv(GLint location, GLsizei count, const GLfloat *v); + void setUniform1iv(GLint location, GLsizei count, const GLint *v); + void setUniform2iv(GLint location, GLsizei count, const GLint *v); + void setUniform3iv(GLint location, GLsizei count, const GLint *v); + void setUniform4iv(GLint location, GLsizei count, const GLint *v); + void setUniform1uiv(GLint location, GLsizei count, const GLuint *v); + void setUniform2uiv(GLint location, GLsizei count, const GLuint *v); + void setUniform3uiv(GLint location, GLsizei count, const GLuint *v); + void setUniform4uiv(GLint location, GLsizei count, const GLuint *v); + void setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); + void setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value); 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 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); GLint getLength(); - bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader); + bool link(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader, + const std::vector& transformFeedbackVaryings, GLenum transformFeedbackBufferMode); void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders); void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; @@ -107,62 +148,165 @@ class ProgramBinary : public RefCountObject void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const; GLint getActiveUniformCount() const; GLint getActiveUniformMaxLength() const; + GLint getActiveUniformi(GLuint index, GLenum pname) const; + bool isValidUniformLocation(GLint location) const; + LinkedUniform *getUniformByLocation(GLint location) const; + LinkedUniform *getUniformByName(const std::string &name) const; + + void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const; + void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const; + GLuint getActiveUniformBlockCount() const; + GLuint getActiveUniformBlockMaxLength() const; + UniformBlock *getUniformBlockByIndex(GLuint blockIndex); + + GLint getFragDataLocation(const char *name) const; + + size_t getTransformFeedbackVaryingCount() const; + const LinkedVarying &getTransformFeedbackVarying(size_t idx) const; + GLenum getTransformFeedbackBufferMode() const; void validate(InfoLog &infoLog); bool validateSamplers(InfoLog *infoLog); bool isValidated() const; + void updateSamplerMapping(); unsigned int getSerial() const; + int getShaderVersion() const; void initAttributesByLayout(); - void sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const; + void sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const; - static std::string decorateAttribute(const std::string &name); // Prepend an underscore + const std::vector &getUniforms() const { return mUniforms; } + const rx::UniformStorage &getVertexUniformStorage() const { return *mVertexUniformStorage; } + const rx::UniformStorage &getFragmentUniformStorage() const { return *mFragmentUniformStorage; } private: DISALLOW_COPY_AND_ASSIGN(ProgramBinary); - int packVaryings(InfoLog &infoLog, const Varying *packing[][4], FragmentShader *fragmentShader); - bool linkVaryings(InfoLog &infoLog, int registers, const Varying *packing[][4], - std::string& pixelHLSL, std::string& vertexHLSL, - FragmentShader *fragmentShader, VertexShader *vertexShader); + struct Sampler + { + Sampler(); + + bool active; + GLint logicalTextureUnit; + TextureType textureType; + }; + void reset(); + + bool linkVaryings(InfoLog &infoLog, FragmentShader *fragmentShader, VertexShader *vertexShader); bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, FragmentShader *fragmentShader, VertexShader *vertexShader); - bool linkUniforms(InfoLog &infoLog, const sh::ActiveUniforms &vertexUniforms, const sh::ActiveUniforms &fragmentUniforms); - bool defineUniform(GLenum shader, const sh::Uniform &constant, InfoLog &infoLog); - - std::string generateGeometryShaderHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const; - std::string generatePointSpriteHLSL(int registers, const Varying *packing[][4], FragmentShader *fragmentShader, VertexShader *vertexShader) const; + 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); + + 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); + 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); + static bool assignSamplers(unsigned int startSamplerIndex, GLenum samplerType, unsigned int samplerCount, + Sampler *outArray, GLuint *usedRange, unsigned int limit); + bool areMatchingInterfaceBlocks(InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock, const sh::InterfaceBlock &fragmentInterfaceBlock); + bool linkUniformBlocks(InfoLog &infoLog, const VertexShader &vertexShader, const FragmentShader &fragmentShader); + 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(); + + template + void setUniform(GLint location, GLsizei count, const T* v, GLenum targetUniformType); + + template + void setUniformMatrixfv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value, GLenum targetUniformType); + + template + bool getUniformv(GLint location, GLsizei *bufSize, T *params, GLenum uniformType); + + class VertexExecutable + { + public: + VertexExecutable(const VertexFormat inputLayout[MAX_VERTEX_ATTRIBS], + const GLenum signature[MAX_VERTEX_ATTRIBS], + rx::ShaderExecutable *shaderExecutable); + ~VertexExecutable(); + + bool matchesSignature(const GLenum convertedLayout[MAX_VERTEX_ATTRIBS]) const; + + const VertexFormat *inputs() const { return mInputs; } + const GLenum *signature() const { return mSignature; } + rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } + + private: + VertexFormat mInputs[MAX_VERTEX_ATTRIBS]; + GLenum mSignature[MAX_VERTEX_ATTRIBS]; + rx::ShaderExecutable *mShaderExecutable; + }; + + class PixelExecutable + { + public: + 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; */ } + + const std::vector &outputSignature() const { return mOutputSignature; } + rx::ShaderExecutable *shaderExecutable() const { return mShaderExecutable; } + + private: + std::vector mOutputSignature; + rx::ShaderExecutable *mShaderExecutable; + }; rx::Renderer *const mRenderer; + DynamicHLSL *mDynamicHLSL; + + 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 *mPixelExecutable; - rx::ShaderExecutable *mVertexExecutable; rx::ShaderExecutable *mGeometryExecutable; - Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS]; + sh::Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS]; + sh::Attribute mShaderAttributes[MAX_VERTEX_ATTRIBS]; int mSemanticIndex[MAX_VERTEX_ATTRIBS]; int mAttributesByLayout[MAX_VERTEX_ATTRIBS]; - struct Sampler - { - Sampler(); - - bool active; - GLint logicalTextureUnit; - TextureType textureType; - }; + GLenum mTransformFeedbackBufferMode; + std::vector mTransformFeedbackLinkedVaryings; Sampler mSamplersPS[MAX_TEXTURE_IMAGE_UNITS]; Sampler mSamplersVS[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; GLuint mUsedVertexSamplerRange; GLuint mUsedPixelSamplerRange; bool mUsesPointSize; + int mShaderVersion; + bool mDirtySamplerMapping; - UniformArray mUniforms; - typedef std::vector UniformIndex; - UniformIndex mUniformIndex; + std::vector mUniforms; + std::vector mUniformBlocks; + std::vector mUniformIndex; + std::map mOutputVariables; + rx::UniformStorage *mVertexUniformStorage; + rx::UniformStorage *mFragmentUniformStorage; bool mValidated; @@ -171,6 +315,7 @@ class ProgramBinary : public RefCountObject static unsigned int issueSerial(); static unsigned int mCurrentSerial; }; + } #endif // LIBGLESV2_PROGRAM_BINARY_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Query.cpp b/src/3rdparty/angle/src/libGLESv2/Query.cpp index bd987954f1..6546d06c34 100644 --- a/src/3rdparty/angle/src/libGLESv2/Query.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Query.cpp @@ -49,4 +49,9 @@ 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 e9b95b729b..a4726a8e73 100644 --- a/src/3rdparty/angle/src/libGLESv2/Query.h +++ b/src/3rdparty/angle/src/libGLESv2/Query.h @@ -9,8 +9,7 @@ #ifndef LIBGLESV2_QUERY_H_ #define LIBGLESV2_QUERY_H_ -#define GL_APICALL -#include +#include "angle_gl.h" #include "common/angleutils.h" #include "common/RefCountObject.h" @@ -37,6 +36,7 @@ class Query : public RefCountObject GLboolean isResultAvailable(); 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 98d33ec6c3..d4bfaf27a1 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp @@ -14,308 +14,96 @@ #include "libGLESv2/Texture.h" #include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/utilities.h" +#include "common/utilities.h" +#include "libGLESv2/formatutils.h" +#include "libGLESv2/FramebufferAttachment.h" namespace gl { unsigned int RenderbufferStorage::mCurrentSerial = 1; -RenderbufferInterface::RenderbufferInterface() +Renderbuffer::Renderbuffer(GLuint id, RenderbufferStorage *newStorage) + : RefCountObject(id), + mStorage(newStorage) { + ASSERT(mStorage); } -// The default case for classes inherited from RenderbufferInterface is not to -// need to do anything upon the reference count to the parent Renderbuffer incrementing -// or decrementing. -void RenderbufferInterface::addProxyRef(const Renderbuffer *proxy) -{ -} - -void RenderbufferInterface::releaseProxy(const Renderbuffer *proxy) -{ -} - -GLuint RenderbufferInterface::getRedSize() const -{ - return gl::GetRedSize(getActualFormat()); -} - -GLuint RenderbufferInterface::getGreenSize() const -{ - return gl::GetGreenSize(getActualFormat()); -} - -GLuint RenderbufferInterface::getBlueSize() const -{ - return gl::GetBlueSize(getActualFormat()); -} - -GLuint RenderbufferInterface::getAlphaSize() const -{ - return gl::GetAlphaSize(getActualFormat()); -} - -GLuint RenderbufferInterface::getDepthSize() const -{ - return gl::GetDepthSize(getActualFormat()); -} - -GLuint RenderbufferInterface::getStencilSize() const -{ - return gl::GetStencilSize(getActualFormat()); -} - -///// RenderbufferTexture2D Implementation //////// - -RenderbufferTexture2D::RenderbufferTexture2D(Texture2D *texture, GLenum target) : mTarget(target) -{ - mTexture2D.set(texture); -} - -RenderbufferTexture2D::~RenderbufferTexture2D() -{ - mTexture2D.set(NULL); -} - -// Textures need to maintain their own reference count for references via -// Renderbuffers acting as proxies. Here, we notify the texture of a reference. -void RenderbufferTexture2D::addProxyRef(const Renderbuffer *proxy) -{ - mTexture2D->addProxyRef(proxy); -} - -void RenderbufferTexture2D::releaseProxy(const Renderbuffer *proxy) -{ - mTexture2D->releaseProxy(proxy); -} - -rx::RenderTarget *RenderbufferTexture2D::getRenderTarget() -{ - return mTexture2D->getRenderTarget(mTarget); -} - -rx::RenderTarget *RenderbufferTexture2D::getDepthStencil() -{ - return mTexture2D->getDepthStencil(mTarget); -} - -GLsizei RenderbufferTexture2D::getWidth() const -{ - return mTexture2D->getWidth(0); -} - -GLsizei RenderbufferTexture2D::getHeight() const -{ - return mTexture2D->getHeight(0); -} - -GLenum RenderbufferTexture2D::getInternalFormat() const -{ - return mTexture2D->getInternalFormat(0); -} - -GLenum RenderbufferTexture2D::getActualFormat() const -{ - return mTexture2D->getActualFormat(0); -} - -GLsizei RenderbufferTexture2D::getSamples() const -{ - return 0; -} - -unsigned int RenderbufferTexture2D::getSerial() const -{ - return mTexture2D->getRenderTargetSerial(mTarget); -} - -unsigned int RenderbufferTexture2D::getTextureSerial() const -{ - return mTexture2D->getTextureSerial(); -} - -///// RenderbufferTextureCubeMap Implementation //////// - -RenderbufferTextureCubeMap::RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target) : mTarget(target) -{ - mTextureCubeMap.set(texture); -} - -RenderbufferTextureCubeMap::~RenderbufferTextureCubeMap() -{ - mTextureCubeMap.set(NULL); -} - -// Textures need to maintain their own reference count for references via -// Renderbuffers acting as proxies. Here, we notify the texture of a reference. -void RenderbufferTextureCubeMap::addProxyRef(const Renderbuffer *proxy) -{ - mTextureCubeMap->addProxyRef(proxy); -} - -void RenderbufferTextureCubeMap::releaseProxy(const Renderbuffer *proxy) -{ - mTextureCubeMap->releaseProxy(proxy); -} - -rx::RenderTarget *RenderbufferTextureCubeMap::getRenderTarget() -{ - return mTextureCubeMap->getRenderTarget(mTarget); -} - -rx::RenderTarget *RenderbufferTextureCubeMap::getDepthStencil() -{ - return NULL; -} - -GLsizei RenderbufferTextureCubeMap::getWidth() const -{ - return mTextureCubeMap->getWidth(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0); -} - -GLsizei RenderbufferTextureCubeMap::getHeight() const -{ - return mTextureCubeMap->getHeight(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0); -} - -GLenum RenderbufferTextureCubeMap::getInternalFormat() const -{ - return mTextureCubeMap->getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0); -} - -GLenum RenderbufferTextureCubeMap::getActualFormat() const -{ - return mTextureCubeMap->getActualFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0); -} - -GLsizei RenderbufferTextureCubeMap::getSamples() const -{ - return 0; -} - -unsigned int RenderbufferTextureCubeMap::getSerial() const -{ - return mTextureCubeMap->getRenderTargetSerial(mTarget); -} - -unsigned int RenderbufferTextureCubeMap::getTextureSerial() const -{ - return mTextureCubeMap->getTextureSerial(); -} - -////// Renderbuffer Implementation ////// - -Renderbuffer::Renderbuffer(rx::Renderer *renderer, GLuint id, RenderbufferInterface *instance) : RefCountObject(id) -{ - ASSERT(instance != NULL); - mInstance = instance; -} - -Renderbuffer::~Renderbuffer() -{ - delete mInstance; -} - -// The RenderbufferInterface contained in this Renderbuffer may need to maintain -// its own reference count, so we pass it on here. -void Renderbuffer::addRef() const -{ - mInstance->addProxyRef(this); - - RefCountObject::addRef(); -} - -void Renderbuffer::release() const +void Renderbuffer::setStorage(RenderbufferStorage *newStorage) { - mInstance->releaseProxy(this); + ASSERT(newStorage); - RefCountObject::release(); + SafeDelete(mStorage); + mStorage = newStorage; } -rx::RenderTarget *Renderbuffer::getRenderTarget() +RenderbufferStorage *Renderbuffer::getStorage() { - return mInstance->getRenderTarget(); -} - -rx::RenderTarget *Renderbuffer::getDepthStencil() -{ - return mInstance->getDepthStencil(); + ASSERT(mStorage); + return mStorage; } GLsizei Renderbuffer::getWidth() const { - return mInstance->getWidth(); + ASSERT(mStorage); + return mStorage->getWidth(); } GLsizei Renderbuffer::getHeight() const { - return mInstance->getHeight(); + ASSERT(mStorage); + return mStorage->getHeight(); } GLenum Renderbuffer::getInternalFormat() const { - return mInstance->getInternalFormat(); + ASSERT(mStorage); + return mStorage->getInternalFormat(); } GLenum Renderbuffer::getActualFormat() const { - return mInstance->getActualFormat(); + ASSERT(mStorage); + return mStorage->getActualFormat(); +} + +GLsizei Renderbuffer::getSamples() const +{ + ASSERT(mStorage); + return mStorage->getSamples(); } GLuint Renderbuffer::getRedSize() const { - return mInstance->getRedSize(); + return gl::GetRedBits(getActualFormat()); } GLuint Renderbuffer::getGreenSize() const { - return mInstance->getGreenSize(); + return gl::GetGreenBits(getActualFormat()); } GLuint Renderbuffer::getBlueSize() const { - return mInstance->getBlueSize(); + return gl::GetBlueBits(getActualFormat()); } GLuint Renderbuffer::getAlphaSize() const { - return mInstance->getAlphaSize(); + return gl::GetAlphaBits(getActualFormat()); } GLuint Renderbuffer::getDepthSize() const { - return mInstance->getDepthSize(); + return gl::GetDepthBits(getActualFormat()); } GLuint Renderbuffer::getStencilSize() const { - return mInstance->getStencilSize(); -} - -GLsizei Renderbuffer::getSamples() const -{ - return mInstance->getSamples(); -} - -unsigned int Renderbuffer::getSerial() const -{ - return mInstance->getSerial(); -} - -unsigned int Renderbuffer::getTextureSerial() const -{ - return mInstance->getTextureSerial(); + return gl::GetStencilBits(getActualFormat()); } -void Renderbuffer::setStorage(RenderbufferStorage *newStorage) -{ - ASSERT(newStorage != NULL); - - delete mInstance; - mInstance = newStorage; -} - -RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerial()) +RenderbufferStorage::RenderbufferStorage() : mSerial(issueSerials(1)) { mWidth = 0; mHeight = 0; @@ -368,16 +156,21 @@ unsigned int RenderbufferStorage::getSerial() const return mSerial; } -unsigned int RenderbufferStorage::issueSerial() +unsigned int RenderbufferStorage::issueSerials(GLuint count) { - return mCurrentSerial++; + unsigned int firstSerial = mCurrentSerial; + mCurrentSerial += count; + return firstSerial; } -unsigned int RenderbufferStorage::issueCubeSerials() +bool RenderbufferStorage::isTexture() const { - unsigned int firstSerial = mCurrentSerial; - mCurrentSerial += 6; - return firstSerial; + return false; +} + +unsigned int RenderbufferStorage::getTextureSerial() const +{ + return -1; } Colorbuffer::Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain) @@ -396,7 +189,7 @@ Colorbuffer::Colorbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain) Colorbuffer::Colorbuffer(rx::Renderer *renderer, int width, int height, GLenum format, GLsizei samples) : mRenderTarget(NULL) { - mRenderTarget = renderer->createRenderTarget(width, height, format, samples, false); + mRenderTarget = renderer->createRenderTarget(width, height, format, samples); if (mRenderTarget) { @@ -418,12 +211,7 @@ Colorbuffer::~Colorbuffer() rx::RenderTarget *Colorbuffer::getRenderTarget() { - if (mRenderTarget) - { - return mRenderTarget; - } - - return NULL; + return mRenderTarget; } DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *swapChain) @@ -442,7 +230,7 @@ DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, rx::SwapChain *sw DepthStencilbuffer::DepthStencilbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) { - mDepthStencil = renderer->createRenderTarget(width, height, GL_DEPTH24_STENCIL8_OES, samples, true); + mDepthStencil = renderer->createRenderTarget(width, height, GL_DEPTH24_STENCIL8_OES, samples); mWidth = mDepthStencil->getWidth(); mHeight = mDepthStencil->getHeight(); @@ -461,12 +249,7 @@ DepthStencilbuffer::~DepthStencilbuffer() rx::RenderTarget *DepthStencilbuffer::getDepthStencil() { - if (mDepthStencil) - { - return mDepthStencil; - } - - return NULL; + return mDepthStencil; } Depthbuffer::Depthbuffer(rx::Renderer *renderer, int width, int height, GLsizei samples) : DepthStencilbuffer(renderer, width, height, samples) diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h index d46fd44557..e2d0c6b0fd 100644 --- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h +++ b/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h @@ -12,8 +12,7 @@ #ifndef LIBGLESV2_RENDERBUFFER_H_ #define LIBGLESV2_RENDERBUFFER_H_ -#define GL_APICALL -#include +#include "angle_gl.h" #include "common/angleutils.h" #include "common/RefCountObject.h" @@ -23,35 +22,32 @@ namespace rx class Renderer; class SwapChain; class RenderTarget; +class TextureStorage; } namespace gl { -class Texture2D; -class TextureCubeMap; -class Renderbuffer; -class Colorbuffer; -class DepthStencilbuffer; +class RenderbufferStorage; +class FramebufferAttachment; -class RenderbufferInterface +// A GL renderbuffer object is usually used as a depth or stencil buffer attachment +// for a framebuffer object. The renderbuffer itself is a distinct GL object, see +// FramebufferAttachment and Framebuffer for how they are applied to an FBO via an +// attachment point. + +class Renderbuffer : public RefCountObject { public: - RenderbufferInterface(); - - virtual ~RenderbufferInterface() {}; - - virtual void addProxyRef(const Renderbuffer *proxy); - virtual void releaseProxy(const Renderbuffer *proxy); - - virtual rx::RenderTarget *getRenderTarget() = 0; - virtual rx::RenderTarget *getDepthStencil() = 0; + Renderbuffer(GLuint id, RenderbufferStorage *newStorage); - 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; + void setStorage(RenderbufferStorage *newStorage); + RenderbufferStorage *getStorage(); + GLsizei getWidth() const; + GLsizei getHeight() const; + GLenum getInternalFormat() const; + GLenum getActualFormat() const; + GLsizei getSamples() const; GLuint getRedSize() const; GLuint getGreenSize() const; GLuint getBlueSize() const; @@ -59,75 +55,14 @@ class RenderbufferInterface GLuint getDepthSize() const; GLuint getStencilSize() const; - virtual unsigned int getSerial() const = 0; - virtual unsigned int getTextureSerial() const = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderbufferInterface); -}; - -class RenderbufferTexture2D : public RenderbufferInterface -{ - public: - RenderbufferTexture2D(Texture2D *texture, GLenum target); - - virtual ~RenderbufferTexture2D(); - - void addProxyRef(const Renderbuffer *proxy); - void releaseProxy(const Renderbuffer *proxy); - - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - - 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 unsigned int getTextureSerial() const; - private: - DISALLOW_COPY_AND_ASSIGN(RenderbufferTexture2D); - - BindingPointer mTexture2D; - GLenum mTarget; -}; - -class RenderbufferTextureCubeMap : public RenderbufferInterface -{ - public: - RenderbufferTextureCubeMap(TextureCubeMap *texture, GLenum target); - - virtual ~RenderbufferTextureCubeMap(); - - void addProxyRef(const Renderbuffer *proxy); - void releaseProxy(const Renderbuffer *proxy); - - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - - 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 unsigned int getTextureSerial() const; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderbufferTextureCubeMap); - - BindingPointer mTextureCubeMap; - GLenum mTarget; + RenderbufferStorage *mStorage; }; // A class derived from RenderbufferStorage is created whenever glRenderbufferStorage // is called. The specific concrete type depends on whether the internal format is // colour depth, stencil or packed depth/stencil. -class RenderbufferStorage : public RenderbufferInterface +class RenderbufferStorage { public: RenderbufferStorage(); @@ -144,10 +79,11 @@ class RenderbufferStorage : public RenderbufferInterface virtual GLsizei getSamples() const; virtual unsigned int getSerial() const; - virtual unsigned int getTextureSerial() const { return 0; } - static unsigned int issueSerial(); - static unsigned int issueCubeSerials(); + virtual bool isTexture() const; + virtual unsigned int getTextureSerial() const; + + static unsigned int issueSerials(GLuint count); protected: GLsizei mWidth; @@ -164,49 +100,6 @@ class RenderbufferStorage : public RenderbufferInterface static unsigned int mCurrentSerial; }; -// Renderbuffer implements the GL renderbuffer object. -// It's only a proxy for a RenderbufferInterface instance; the internal object -// can change whenever glRenderbufferStorage is called. -class Renderbuffer : public RefCountObject -{ - public: - Renderbuffer(rx::Renderer *renderer, GLuint id, RenderbufferInterface *storage); - - virtual ~Renderbuffer(); - - // These functions from RefCountObject are overloaded here because - // Textures need to maintain their own count of references to them via - // Renderbuffers/RenderbufferTextures. These functions invoke those - // reference counting functions on the RenderbufferInterface. - void addRef() const; - void release() const; - - rx::RenderTarget *getRenderTarget(); - rx::RenderTarget *getDepthStencil(); - - GLsizei getWidth() const; - GLsizei getHeight() const; - GLenum getInternalFormat() const; - GLenum getActualFormat() const; - GLuint getRedSize() const; - GLuint getGreenSize() const; - GLuint getBlueSize() const; - GLuint getAlphaSize() const; - GLuint getDepthSize() const; - GLuint getStencilSize() const; - GLsizei getSamples() const; - - unsigned int getSerial() const; - unsigned int getTextureSerial() const; - - void setStorage(RenderbufferStorage *newStorage); - - private: - DISALLOW_COPY_AND_ASSIGN(Renderbuffer); - - RenderbufferInterface *mInstance; -}; - class Colorbuffer : public RenderbufferStorage { public: @@ -261,6 +154,7 @@ class Stencilbuffer : public DepthStencilbuffer private: DISALLOW_COPY_AND_ASSIGN(Stencilbuffer); }; + } #endif // LIBGLESV2_RENDERBUFFER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp index 58dd44fd95..3606532404 100644 --- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp +++ b/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -15,6 +15,9 @@ #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/Shader.h" #include "libGLESv2/Texture.h" +#include "libGLESv2/Sampler.h" +#include "libGLESv2/Fence.h" +#include "libGLESv2/renderer/Renderer.h" namespace gl { @@ -50,6 +53,16 @@ ResourceManager::~ResourceManager() { deleteTexture(mTextureMap.begin()->first); } + + while (!mSamplerMap.empty()) + { + deleteSampler(mSamplerMap.begin()->first); + } + + while (!mFenceSyncMap.empty()) + { + deleteFenceSync(mFenceSyncMap.begin()->first); + } } void ResourceManager::addRef() @@ -123,6 +136,26 @@ GLuint ResourceManager::createRenderbuffer() return handle; } +// Returns an unused sampler name +GLuint ResourceManager::createSampler() +{ + GLuint handle = mSamplerHandleAllocator.allocate(); + + mSamplerMap[handle] = NULL; + + return handle; +} + +// Returns the next unused fence name, and allocates the fence +GLuint ResourceManager::createFenceSync() +{ + GLuint handle = mFenceSyncHandleAllocator.allocate(); + + mFenceSyncMap[handle] = new FenceSync(mRenderer, handle); + + return handle; +} + void ResourceManager::deleteBuffer(GLuint buffer) { BufferMap::iterator bufferObject = mBufferMap.find(buffer); @@ -197,6 +230,30 @@ void ResourceManager::deleteRenderbuffer(GLuint renderbuffer) } } +void ResourceManager::deleteSampler(GLuint sampler) +{ + auto samplerObject = mSamplerMap.find(sampler); + + if (samplerObject != mSamplerMap.end()) + { + mSamplerHandleAllocator.release(samplerObject->first); + if (samplerObject->second) samplerObject->second->release(); + mSamplerMap.erase(samplerObject); + } +} + +void ResourceManager::deleteFenceSync(GLuint fenceSync) +{ + auto fenceObjectIt = mFenceSyncMap.find(fenceSync); + + if (fenceObjectIt != mFenceSyncMap.end()) + { + mFenceSyncHandleAllocator.release(fenceObjectIt->first); + if (fenceObjectIt->second) fenceObjectIt->second->release(); + mFenceSyncMap.erase(fenceObjectIt); + } +} + Buffer *ResourceManager::getBuffer(unsigned int handle) { BufferMap::iterator buffer = mBufferMap.find(handle); @@ -269,6 +326,34 @@ Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle) } } +Sampler *ResourceManager::getSampler(unsigned int handle) +{ + auto sampler = mSamplerMap.find(handle); + + if (sampler == mSamplerMap.end()) + { + return NULL; + } + else + { + return sampler->second; + } +} + +FenceSync *ResourceManager::getFenceSync(unsigned int handle) +{ + auto fenceObjectIt = mFenceSyncMap.find(handle); + + if (fenceObjectIt == mFenceSyncMap.end()) + { + return NULL; + } + else + { + return fenceObjectIt->second; + } +} + void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer) { mRenderbufferMap[handle] = buffer; @@ -278,7 +363,7 @@ void ResourceManager::checkBufferAllocation(unsigned int buffer) { if (buffer != 0 && !getBuffer(buffer)) { - Buffer *bufferObject = new Buffer(mRenderer, buffer); + Buffer *bufferObject = new Buffer(mRenderer->createBuffer(), buffer); mBufferMap[buffer] = bufferObject; bufferObject->addRef(); } @@ -292,11 +377,19 @@ void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type) if (type == TEXTURE_2D) { - textureObject = new Texture2D(mRenderer, texture); + textureObject = new Texture2D(mRenderer->createTexture2D(), texture); } else if (type == TEXTURE_CUBE) { - textureObject = new TextureCubeMap(mRenderer, texture); + textureObject = new TextureCubeMap(mRenderer->createTextureCube(), texture); + } + else if (type == TEXTURE_3D) + { + textureObject = new Texture3D(mRenderer->createTexture3D(), texture); + } + else if (type == TEXTURE_2D_ARRAY) + { + textureObject = new Texture2DArray(mRenderer->createTexture2DArray(), texture); } else { @@ -313,10 +406,25 @@ void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer) { if (renderbuffer != 0 && !getRenderbuffer(renderbuffer)) { - Renderbuffer *renderbufferObject = new Renderbuffer(mRenderer, renderbuffer, new Colorbuffer(mRenderer, 0, 0, GL_RGBA4, 0)); + Renderbuffer *renderbufferObject = new Renderbuffer(renderbuffer, new Colorbuffer(mRenderer, 0, 0, GL_RGBA4, 0)); mRenderbufferMap[renderbuffer] = renderbufferObject; renderbufferObject->addRef(); } } +void ResourceManager::checkSamplerAllocation(GLuint sampler) +{ + if (sampler != 0 && !getSampler(sampler)) + { + Sampler *samplerObject = new Sampler(sampler); + mSamplerMap[sampler] = samplerObject; + samplerObject->addRef(); + } +} + +bool ResourceManager::isSampler(GLuint sampler) +{ + return mSamplerMap.find(sampler) != mSamplerMap.end(); +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h index e99c77c35d..d646c0d3cf 100644 --- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h +++ b/src/3rdparty/angle/src/libGLESv2/ResourceManager.h @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -10,14 +10,9 @@ #ifndef LIBGLESV2_RESOURCEMANAGER_H_ #define LIBGLESV2_RESOURCEMANAGER_H_ -#define GL_APICALL -#include +#include "angle_gl.h" -#ifdef _MSC_VER -#include -#else #include -#endif #include "common/angleutils.h" #include "libGLESv2/angletypes.h" @@ -35,6 +30,8 @@ class Shader; class Program; class Texture; class Renderbuffer; +class Sampler; +class FenceSync; class ResourceManager { @@ -50,24 +47,33 @@ class ResourceManager GLuint createProgram(); GLuint createTexture(); GLuint createRenderbuffer(); + GLuint createSampler(); + GLuint createFenceSync(); void deleteBuffer(GLuint buffer); void deleteShader(GLuint shader); void deleteProgram(GLuint program); void deleteTexture(GLuint texture); void deleteRenderbuffer(GLuint renderbuffer); + void deleteSampler(GLuint sampler); + void deleteFenceSync(GLuint fenceSync); Buffer *getBuffer(GLuint handle); Shader *getShader(GLuint handle); Program *getProgram(GLuint handle); Texture *getTexture(GLuint handle); Renderbuffer *getRenderbuffer(GLuint handle); + Sampler *getSampler(GLuint handle); + FenceSync *getFenceSync(GLuint handle); void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer); void checkBufferAllocation(unsigned int buffer); void checkTextureAllocation(GLuint texture, TextureType type); void checkRenderbufferAllocation(GLuint renderbuffer); + void checkSamplerAllocation(GLuint sampler); + + bool isSampler(GLuint sampler); private: DISALLOW_COPY_AND_ASSIGN(ResourceManager); @@ -75,32 +81,32 @@ class ResourceManager std::size_t mRefCount; rx::Renderer *mRenderer; -#ifndef HASH_MAP -# ifdef _MSC_VER -# define HASH_MAP stdext::hash_map -# else -# define HASH_MAP std::unordered_map -# endif -#endif - - typedef HASH_MAP BufferMap; + typedef std::unordered_map BufferMap; BufferMap mBufferMap; HandleAllocator mBufferHandleAllocator; - typedef HASH_MAP ShaderMap; + typedef std::unordered_map ShaderMap; ShaderMap mShaderMap; - typedef HASH_MAP ProgramMap; + typedef std::unordered_map ProgramMap; ProgramMap mProgramMap; HandleAllocator mProgramShaderHandleAllocator; - typedef HASH_MAP TextureMap; + typedef std::unordered_map TextureMap; TextureMap mTextureMap; HandleAllocator mTextureHandleAllocator; - typedef HASH_MAP RenderbufferMap; + typedef std::unordered_map RenderbufferMap; RenderbufferMap mRenderbufferMap; HandleAllocator mRenderbufferHandleAllocator; + + typedef std::unordered_map SamplerMap; + SamplerMap mSamplerMap; + HandleAllocator mSamplerHandleAllocator; + + typedef std::unordered_map FenceMap; + FenceMap mFenceSyncMap; + HandleAllocator mFenceSyncHandleAllocator; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/Sampler.cpp b/src/3rdparty/angle/src/libGLESv2/Sampler.cpp new file mode 100644 index 0000000000..ed6e29f89e --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/Sampler.cpp @@ -0,0 +1,44 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Sampler.cpp : Implements the Sampler class, which represents a GLES 3 +// sampler object. Sampler objects store some state needed to sample textures. + +#include "libGLESv2/Sampler.h" +#include "libGLESv2/angletypes.h" + +namespace gl +{ + +Sampler::Sampler(GLuint id) + : RefCountObject(id), + mMinFilter(GL_NEAREST_MIPMAP_LINEAR), + mMagFilter(GL_LINEAR), + mWrapS(GL_REPEAT), + mWrapT(GL_REPEAT), + mWrapR(GL_REPEAT), + mMinLod(-1000.0f), + mMaxLod(1000.0f), + mComparisonMode(GL_NONE), + mComparisonFunc(GL_LEQUAL) +{ +} + +void Sampler::getState(SamplerState *samplerState) const +{ + samplerState->minFilter = mMinFilter; + samplerState->magFilter = mMagFilter; + samplerState->wrapS = mWrapS; + samplerState->wrapT = mWrapT; + samplerState->wrapR = mWrapR; + samplerState->minLod = mMinLod; + samplerState->maxLod = mMaxLod; + samplerState->compareMode = mComparisonMode; + samplerState->compareFunc = mComparisonFunc; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/Sampler.h b/src/3rdparty/angle/src/libGLESv2/Sampler.h new file mode 100644 index 0000000000..257bc25d22 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/Sampler.h @@ -0,0 +1,60 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Sampler.h : Defines the Sampler class, which represents a GLES 3 +// sampler object. Sampler objects store some state needed to sample textures. + +#ifndef LIBGLESV2_SAMPLER_H_ +#define LIBGLESV2_SAMPLER_H_ + +#include "common/RefCountObject.h" + +namespace gl +{ +struct SamplerState; + +class Sampler : public RefCountObject +{ + public: + Sampler(GLuint id); + + void setMinFilter(GLenum minFilter) { mMinFilter = minFilter; } + void setMagFilter(GLenum magFilter) { mMagFilter = magFilter; } + void setWrapS(GLenum wrapS) { mWrapS = wrapS; } + void setWrapT(GLenum wrapT) { mWrapT = wrapT; } + void setWrapR(GLenum wrapR) { mWrapR = wrapR; } + void setMinLod(GLfloat minLod) { mMinLod = minLod; } + void setMaxLod(GLfloat maxLod) { mMaxLod = maxLod; } + void setComparisonMode(GLenum comparisonMode) { mComparisonMode = comparisonMode; } + void setComparisonFunc(GLenum comparisonFunc) { mComparisonFunc = comparisonFunc; } + + GLenum getMinFilter() const { return mMinFilter; } + GLenum getMagFilter() const { return mMagFilter; } + GLenum getWrapS() const { return mWrapS; } + GLenum getWrapT() const { return mWrapT; } + GLenum getWrapR() const { return mWrapR; } + GLfloat getMinLod() const { return mMinLod; } + GLfloat getMaxLod() const { return mMaxLod; } + GLenum getComparisonMode() const { return mComparisonMode; } + GLenum getComparisonFunc() const { return mComparisonFunc; } + + void getState(SamplerState *samplerState) const; + + private: + GLenum mMinFilter; + GLenum mMagFilter; + GLenum mWrapS; + GLenum mWrapT; + GLenum mWrapR; + GLfloat mMinLod; + GLfloat mMaxLod; + GLenum mComparisonMode; + GLenum mComparisonFunc; +}; + +} + +#endif // LIBGLESV2_SAMPLER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp index f6a2f03dfc..eda0298e87 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Shader.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" // -// Copyright (c) 2002-2013 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. // @@ -12,7 +12,7 @@ #include "libGLESv2/Shader.h" #include "GLSLANG/ShaderLang.h" -#include "libGLESv2/utilities.h" +#include "common/utilities.h" #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/Constants.h" #include "libGLESv2/ResourceManager.h" @@ -25,22 +25,16 @@ void *Shader::mVertexCompiler = NULL; Shader::Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle) : mHandle(handle), mRenderer(renderer), mResourceManager(manager) { - mSource = NULL; - mHlsl = NULL; - mInfoLog = NULL; - uncompile(); initializeCompiler(); mRefCount = 0; mDeleteStatus = false; + mShaderVersion = 100; } Shader::~Shader() { - delete[] mSource; - delete[] mHlsl; - delete[] mInfoLog; } GLuint Shader::getHandle() const @@ -48,69 +42,31 @@ GLuint Shader::getHandle() const return mHandle; } -void Shader::setSource(GLsizei count, const char **string, const GLint *length) +void Shader::setSource(GLsizei count, const char *const *string, const GLint *length) { - delete[] mSource; - int totalLength = 0; + std::ostringstream stream; for (int i = 0; i < count; i++) { - if (length && length[i] >= 0) - { - totalLength += length[i]; - } - else - { - totalLength += (int)strlen(string[i]); - } + stream << string[i]; } - mSource = new char[totalLength + 1]; - char *code = mSource; - - for (int i = 0; i < count; i++) - { - int stringLength; - - if (length && length[i] >= 0) - { - stringLength = length[i]; - } - else - { - stringLength = (int)strlen(string[i]); - } - - strncpy(code, string[i], stringLength); - code += stringLength; - } - - mSource[totalLength] = '\0'; + mSource = stream.str(); } int Shader::getInfoLogLength() const { - if (!mInfoLog) - { - return 0; - } - else - { - return strlen(mInfoLog) + 1; - } + return mInfoLog.empty() ? 0 : (mInfoLog.length() + 1); } -void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) +void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const { int index = 0; if (bufSize > 0) { - if (mInfoLog) - { - index = std::min(bufSize - 1, (int)strlen(mInfoLog)); - memcpy(infoLog, mInfoLog, index); - } + index = std::min(bufSize - 1, static_cast(mInfoLog.length())); + memcpy(infoLog, mInfoLog.c_str(), index); infoLog[index] = '\0'; } @@ -123,39 +79,22 @@ void Shader::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) int Shader::getSourceLength() const { - if (!mSource) - { - return 0; - } - else - { - return strlen(mSource) + 1; - } + return mSource.empty() ? 0 : (mSource.length() + 1); } int Shader::getTranslatedSourceLength() const { - if (!mHlsl) - { - return 0; - } - else - { - return strlen(mHlsl) + 1; - } + return mHlsl.empty() ? 0 : (mHlsl.length() + 1); } -void Shader::getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer) +void Shader::getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) const { int index = 0; if (bufSize > 0) { - if (source) - { - index = std::min(bufSize - 1, (int)strlen(source)); - memcpy(buffer, source, index); - } + index = std::min(bufSize - 1, static_cast(source.length())); + memcpy(buffer, source.c_str(), index); buffer[index] = '\0'; } @@ -166,27 +105,49 @@ void Shader::getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char } } -void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) +void Shader::getSource(GLsizei bufSize, GLsizei *length, char *buffer) const { getSourceImpl(mSource, bufSize, length, buffer); } -void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) +void Shader::getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const { getSourceImpl(mHlsl, bufSize, length, buffer); } -const sh::ActiveUniforms &Shader::getUniforms() +unsigned int Shader::getUniformRegister(const std::string &uniformName) const +{ + 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; } -bool Shader::isCompiled() +const std::vector &Shader::getInterfaceBlocks() const +{ + return mActiveInterfaceBlocks; +} + +std::vector &Shader::getVaryings() +{ + return mVaryings; +} + +bool Shader::isCompiled() const { - return mHlsl != NULL; + return !mHlsl.empty(); } -const char *Shader::getHLSL() +const std::string &Shader::getHLSL() const { return mHlsl; } @@ -235,6 +196,10 @@ void Shader::initializeCompiler() 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(); @@ -242,15 +207,21 @@ void Shader::initializeCompiler() resources.MaxCombinedTextureImageUnits = mRenderer->getMaxCombinedTextureImageUnits(); resources.MaxTextureImageUnits = MAX_TEXTURE_IMAGE_UNITS; resources.MaxFragmentUniformVectors = mRenderer->getMaxFragmentUniformVectors(); - resources.MaxDrawBuffers = mRenderer->getMaxRenderTargets(); - resources.OES_standard_derivatives = mRenderer->getDerivativeInstructionSupport(); - resources.EXT_draw_buffers = mRenderer->getMaxRenderTargets() > 1; + 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 - - mFragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); - mVertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, SH_GLES2_SPEC, hlslVersion, &resources); + // 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); } } } @@ -266,57 +237,37 @@ void Shader::releaseCompiler() ShFinalize(); } -void Shader::parseVaryings() +void Shader::parseVaryings(void *compiler) { - if (mHlsl) + if (!mHlsl.empty()) { - const char *input = strstr(mHlsl, "// Varyings") + 12; + std::vector *activeVaryings; + ShGetInfoPointer(compiler, SH_ACTIVE_VARYINGS_ARRAY, reinterpret_cast(&activeVaryings)); - while(true) + for (size_t varyingIndex = 0; varyingIndex < activeVaryings->size(); varyingIndex++) { - char varyingType[256]; - char varyingName[256]; - - int matches = sscanf(input, "static %255s %255s", varyingType, varyingName); - - if (matches != 2) - { - break; - } - - char *array = strstr(varyingName, "["); - int size = 1; - - if (array) - { - size = atoi(array + 1); - *array = '\0'; - } - - mVaryings.push_back(Varying(parseType(varyingType), varyingName, size, array != NULL)); - - input = strstr(input, ";") + 2; + mVaryings.push_back(PackedVarying((*activeVaryings)[varyingIndex])); } - mUsesMultipleRenderTargets = strstr(mHlsl, "GL_USES_MRT") != NULL; - mUsesFragColor = strstr(mHlsl, "GL_USES_FRAG_COLOR") != NULL; - mUsesFragData = strstr(mHlsl, "GL_USES_FRAG_DATA") != NULL; - mUsesFragCoord = strstr(mHlsl, "GL_USES_FRAG_COORD") != NULL; - mUsesFrontFacing = strstr(mHlsl, "GL_USES_FRONT_FACING") != NULL; - mUsesPointSize = strstr(mHlsl, "GL_USES_POINT_SIZE") != NULL; - mUsesPointCoord = strstr(mHlsl, "GL_USES_POINT_COORD") != NULL; - mUsesDepthRange = strstr(mHlsl, "GL_USES_DEPTH_RANGE") != NULL; - mUsesFragDepth = strstr(mHlsl, "GL_USES_FRAG_DEPTH") != NULL; - mUsesDiscardRewriting = strstr(mHlsl, "ANGLE_USES_DISCARD_REWRITING") != NULL; + 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 (VaryingList::iterator var = mVaryings.begin(); var != mVaryings.end(); var++) + for (unsigned int varyingIndex = 0; varyingIndex < mVaryings.size(); varyingIndex++) { - var->reg = -1; - var->col = -1; + mVaryings[varyingIndex].resetRegisterAssignment(); } } @@ -324,10 +275,8 @@ void Shader::resetVaryingsRegisterAssignment() void Shader::uncompile() { // set by compileToHLSL - delete[] mHlsl; - mHlsl = NULL; - delete[] mInfoLog; - mInfoLog = NULL; + mHlsl.clear(); + mInfoLog.clear(); // set by parseVaryings mVaryings.clear(); @@ -341,20 +290,16 @@ void Shader::uncompile() mUsesPointCoord = false; mUsesDepthRange = false; mUsesFragDepth = false; + mShaderVersion = 100; mUsesDiscardRewriting = false; + mUsesNestedBreak = false; mActiveUniforms.clear(); + mActiveInterfaceBlocks.clear(); } void Shader::compileToHLSL(void *compiler) { - // ensure we don't pass a NULL source to the compiler - const char *source = "\0"; - if (mSource) - { - source = mSource; - } - // ensure the compiler is loaded initializeCompiler(); @@ -363,164 +308,163 @@ void Shader::compileToHLSL(void *compiler) if (perfActive()) { sourcePath = getTempPath(); - writeFile(sourcePath.c_str(), source, strlen(source)); + writeFile(sourcePath.c_str(), mSource.c_str(), mSource.length()); compileOptions |= SH_LINE_DIRECTIVES; } int result; if (sourcePath.empty()) { - result = ShCompile(compiler, &source, 1, compileOptions); + const char* sourceStrings[] = + { + mSource.c_str(), + }; + + result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions); } else { - const char* sourceStrings[2] = + const char* sourceStrings[] = { sourcePath.c_str(), - source + mSource.c_str(), }; - result = ShCompile(compiler, sourceStrings, 2, compileOptions | SH_SOURCE_PATH); + result = ShCompile(compiler, sourceStrings, ArraySize(sourceStrings), compileOptions | SH_SOURCE_PATH); } - if (result) + 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); - mHlsl = new char[objCodeLen]; - ShGetObjectCode(compiler, mHlsl); + + 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 = *(sh::ActiveUniforms*)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); - mInfoLog = new char[infoLogLen]; - ShGetInfoLog(compiler, mInfoLog); - TRACE("\n%s", mInfoLog); + char* infoLog = new char[infoLogLen]; + ShGetInfoLog(compiler, infoLog); + mInfoLog = infoLog; + + TRACE("\n%s", mInfoLog.c_str()); } } -GLenum Shader::parseType(const std::string &type) +rx::D3DWorkaroundType Shader::getD3DWorkarounds() const { - if (type == "float") - { - return GL_FLOAT; - } - else if (type == "float2") + if (mUsesDiscardRewriting) { - return GL_FLOAT_VEC2; + // 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; } - else if (type == "float3") - { - return GL_FLOAT_VEC3; - } - else if (type == "float4") - { - return GL_FLOAT_VEC4; - } - else if (type == "float2x2") - { - return GL_FLOAT_MAT2; - } - else if (type == "float3x3") - { - return GL_FLOAT_MAT3; - } - else if (type == "float4x4") + + if (mUsesNestedBreak) { - return GL_FLOAT_MAT4; + // 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; } - else UNREACHABLE(); - return GL_NONE; + return rx::ANGLE_D3D_WORKAROUND_NONE; } // true if varying x has a higher priority in packing than y -bool Shader::compareVarying(const Varying &x, const Varying &y) +bool Shader::compareVarying(const PackedVarying &x, const PackedVarying &y) { - if(x.type == y.type) + if (x.type == y.type) { - return x.size > y.size; + return x.arraySize > y.arraySize; } - switch (x.type) + // Special case for handling structs: we sort these to the end of the list + if (x.type == GL_STRUCT_ANGLEX) { - case GL_FLOAT_MAT4: return true; - case GL_FLOAT_MAT2: - switch(y.type) - { - case GL_FLOAT_MAT4: return false; - case GL_FLOAT_MAT2: return true; - case GL_FLOAT_VEC4: return true; - case GL_FLOAT_MAT3: return true; - case GL_FLOAT_VEC3: return true; - case GL_FLOAT_VEC2: return true; - case GL_FLOAT: return true; - default: UNREACHABLE(); - } - break; - case GL_FLOAT_VEC4: - switch(y.type) - { - case GL_FLOAT_MAT4: return false; - case GL_FLOAT_MAT2: return false; - case GL_FLOAT_VEC4: return true; - case GL_FLOAT_MAT3: return true; - case GL_FLOAT_VEC3: return true; - case GL_FLOAT_VEC2: return true; - case GL_FLOAT: return true; - default: UNREACHABLE(); - } - break; - case GL_FLOAT_MAT3: - switch(y.type) - { - case GL_FLOAT_MAT4: return false; - case GL_FLOAT_MAT2: return false; - case GL_FLOAT_VEC4: return false; - case GL_FLOAT_MAT3: return true; - case GL_FLOAT_VEC3: return true; - case GL_FLOAT_VEC2: return true; - case GL_FLOAT: return true; - default: UNREACHABLE(); - } - break; - case GL_FLOAT_VEC3: - switch(y.type) - { - case GL_FLOAT_MAT4: return false; - case GL_FLOAT_MAT2: return false; - case GL_FLOAT_VEC4: return false; - case GL_FLOAT_MAT3: return false; - case GL_FLOAT_VEC3: return true; - case GL_FLOAT_VEC2: return true; - case GL_FLOAT: return true; - default: UNREACHABLE(); - } - break; - case GL_FLOAT_VEC2: - switch(y.type) - { - case GL_FLOAT_MAT4: return false; - case GL_FLOAT_MAT2: return false; - case GL_FLOAT_VEC4: return false; - case GL_FLOAT_MAT3: return false; - case GL_FLOAT_VEC3: return false; - case GL_FLOAT_VEC2: return true; - case GL_FLOAT: return true; - default: UNREACHABLE(); - } - break; - case GL_FLOAT: return false; - default: UNREACHABLE(); + return false; } - 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) @@ -532,7 +476,7 @@ VertexShader::~VertexShader() { } -GLenum VertexShader::getType() +GLenum VertexShader::getType() const { return GL_VERTEX_SHADER; } @@ -542,7 +486,7 @@ void VertexShader::uncompile() Shader::uncompile(); // set by ParseAttributes - mAttributes.clear(); + mActiveAttributes.clear(); } void VertexShader::compile() @@ -551,7 +495,7 @@ void VertexShader::compile() compileToHLSL(mVertexCompiler); parseAttributes(); - parseVaryings(); + parseVaryings(mVertexCompiler); } int VertexShader::getSemanticIndex(const std::string &attributeName) @@ -559,14 +503,16 @@ int VertexShader::getSemanticIndex(const std::string &attributeName) if (!attributeName.empty()) { int semanticIndex = 0; - for (AttributeArray::iterator attribute = mAttributes.begin(); attribute != mAttributes.end(); attribute++) + for (unsigned int attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++) { - if (attribute->name == attributeName) + const sh::ShaderVariable &attribute = mActiveAttributes[attributeIndex]; + + if (attribute.name == attributeName) { return semanticIndex; } - semanticIndex += VariableRowCount(attribute->type); + semanticIndex += VariableRegisterCount(attribute.type); } } @@ -575,27 +521,12 @@ int VertexShader::getSemanticIndex(const std::string &attributeName) void VertexShader::parseAttributes() { - const char *hlsl = getHLSL(); - if (hlsl) + const std::string &hlsl = getHLSL(); + if (!hlsl.empty()) { - const char *input = strstr(hlsl, "// Attributes") + 14; - - while(true) - { - char attributeType[256]; - char attributeName[256]; - - int matches = sscanf(input, "static %255s _%255s", attributeType, attributeName); - - if (matches != 2) - { - break; - } - - mAttributes.push_back(Attribute(parseType(attributeType), attributeName)); - - input = strstr(input, ";") + 2; - } + void *activeAttributes; + ShGetInfoPointer(mVertexCompiler, SH_ACTIVE_ATTRIBUTES_ARRAY, &activeAttributes); + mActiveAttributes = *(std::vector*)activeAttributes; } } @@ -608,7 +539,7 @@ FragmentShader::~FragmentShader() { } -GLenum FragmentShader::getType() +GLenum FragmentShader::getType() const { return GL_FRAGMENT_SHADER; } @@ -618,7 +549,45 @@ void FragmentShader::compile() uncompile(); compileToHLSL(mFragmentCompiler); - parseVaryings(); - mVaryings.sort(compareVarying); + 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; + } +} + +void FragmentShader::uncompile() +{ + Shader::uncompile(); + + mActiveOutputVariables.clear(); +} + +const std::vector &FragmentShader::getOutputVariables() const +{ + return mActiveOutputVariables; } + +ShShaderOutput Shader::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); +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.h b/src/3rdparty/angle/src/libGLESv2/Shader.h index 2015addd11..a40f415c1e 100644 --- a/src/3rdparty/angle/src/libGLESv2/Shader.h +++ b/src/3rdparty/angle/src/libGLESv2/Shader.h @@ -12,14 +12,15 @@ #ifndef LIBGLESV2_SHADER_H_ #define LIBGLESV2_SHADER_H_ -#define GL_APICALL -#include +#include "angle_gl.h" #include #include #include -#include "compiler/translator/Uniform.h" +#include "common/shadervars.h" #include "common/angleutils.h" +#include "libGLESv2/angletypes.h" +#include "GLSLANG/ShaderLang.h" namespace rx { @@ -30,73 +31,81 @@ namespace gl { class ResourceManager; -struct Varying +struct PackedVarying : public sh::Varying { - Varying(GLenum type, const std::string &name, int size, bool array) - : type(type), name(name), size(size), array(array), reg(-1), col(-1) - { - } + unsigned int registerIndex; // Assigned during link - GLenum type; - std::string name; - int size; // Number of 'type' elements - bool array; + PackedVarying(const sh::Varying &varying) + : sh::Varying(varying), + registerIndex(GL_INVALID_INDEX) + {} - int reg; // First varying register, assigned during link - int col; // First register element, assigned during link -}; + bool registerAssigned() const { return registerIndex != GL_INVALID_INDEX; } -typedef std::list VaryingList; + void resetRegisterAssignment() + { + registerIndex = GL_INVALID_INDEX; + } +}; class Shader { - friend class ProgramBinary; + friend class DynamicHLSL; public: Shader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle); virtual ~Shader(); - virtual GLenum getType() = 0; + virtual GLenum getType() const = 0; GLuint getHandle() const; void deleteSource(); - void setSource(GLsizei count, const char **string, const GLint *length); + void setSource(GLsizei count, const char *const *string, const GLint *length); int getInfoLogLength() const; - void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog); + void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog) const; int getSourceLength() const; - void getSource(GLsizei bufSize, GLsizei *length, char *buffer); + void getSource(GLsizei bufSize, GLsizei *length, char *buffer) const; int getTranslatedSourceLength() const; - void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer); - const sh::ActiveUniforms &getUniforms(); + 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 char *getHLSL(); + bool isCompiled() const; + const std::string &getHLSL() const; 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 resetVaryingsRegisterAssignment(); + void parseVaryings(void *compiler); void compileToHLSL(void *compiler); - void getSourceImpl(char *source, GLsizei bufSize, GLsizei *length, char *buffer); + void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer) const; - static GLenum parseType(const std::string &type); - static bool compareVarying(const Varying &x, const Varying &y); + static bool compareVarying(const PackedVarying &x, const PackedVarying &y); const rx::Renderer *const mRenderer; - VaryingList mVaryings; + std::vector mVaryings; bool mUsesMultipleRenderTargets; bool mUsesFragColor; @@ -107,7 +116,9 @@ class Shader bool mUsesPointCoord; bool mUsesDepthRange; bool mUsesFragDepth; + int mShaderVersion; bool mUsesDiscardRewriting; + bool mUsesNestedBreak; static void *mFragmentCompiler; static void *mVertexCompiler; @@ -121,50 +132,39 @@ class Shader 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 - char *mSource; - char *mHlsl; - char *mInfoLog; - sh::ActiveUniforms mActiveUniforms; + std::string mSource; + std::string mHlsl; + std::string mInfoLog; + std::vector mActiveUniforms; + std::vector mActiveInterfaceBlocks; + std::map mUniformRegisterMap; + std::map mInterfaceBlockRegisterMap; ResourceManager *mResourceManager; }; -struct Attribute -{ - Attribute() : type(GL_NONE), name("") - { - } - - Attribute(GLenum type, const std::string &name) : type(type), name(name) - { - } - - GLenum type; - std::string name; -}; - -typedef std::vector AttributeArray; - class VertexShader : public Shader { - friend class ProgramBinary; + friend class DynamicHLSL; public: VertexShader(ResourceManager *manager, const rx::Renderer *renderer, GLuint handle); ~VertexShader(); - virtual GLenum getType(); + 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(); - AttributeArray mAttributes; + std::vector mActiveAttributes; }; class FragmentShader : public Shader @@ -174,11 +174,15 @@ class FragmentShader : public Shader ~FragmentShader(); - virtual GLenum getType(); + virtual GLenum getType() const; virtual void compile(); + virtual void uncompile(); + const std::vector &getOutputVariables() const; private: DISALLOW_COPY_AND_ASSIGN(FragmentShader); + + std::vector mActiveOutputVariables; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/State.cpp b/src/3rdparty/angle/src/libGLESv2/State.cpp new file mode 100644 index 0000000000..b552701727 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/State.cpp @@ -0,0 +1,1415 @@ +#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 +// found in the LICENSE file. +// + +// State.cpp: Implements the State class, encapsulating raw GL state. + +#include "libGLESv2/State.h" + +#include "libGLESv2/Context.h" +#include "libGLESv2/VertexArray.h" +#include "libGLESv2/Query.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" +#include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/formatutils.h" + +namespace gl +{ +State::State() +{ + mContext = NULL; + + setClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + mDepthClearValue = 1.0f; + mStencilClearValue = 0; + + mRasterizer.rasterizerDiscard = false; + mRasterizer.cullFace = false; + mRasterizer.cullMode = GL_BACK; + mRasterizer.frontFace = GL_CCW; + mRasterizer.polygonOffsetFill = false; + mRasterizer.polygonOffsetFactor = 0.0f; + mRasterizer.polygonOffsetUnits = 0.0f; + mRasterizer.pointDrawMode = false; + mRasterizer.multiSample = false; + mScissorTest = false; + mScissor.x = 0; + mScissor.y = 0; + mScissor.width = 0; + mScissor.height = 0; + + mBlend.blend = false; + mBlend.sourceBlendRGB = GL_ONE; + mBlend.sourceBlendAlpha = GL_ONE; + mBlend.destBlendRGB = GL_ZERO; + mBlend.destBlendAlpha = GL_ZERO; + mBlend.blendEquationRGB = GL_FUNC_ADD; + mBlend.blendEquationAlpha = GL_FUNC_ADD; + mBlend.sampleAlphaToCoverage = false; + mBlend.dither = true; + + mBlendColor.red = 0; + mBlendColor.green = 0; + mBlendColor.blue = 0; + mBlendColor.alpha = 0; + + mDepthStencil.depthTest = false; + mDepthStencil.depthFunc = GL_LESS; + mDepthStencil.depthMask = true; + mDepthStencil.stencilTest = false; + mDepthStencil.stencilFunc = GL_ALWAYS; + mDepthStencil.stencilMask = -1; + mDepthStencil.stencilWritemask = -1; + mDepthStencil.stencilBackFunc = GL_ALWAYS; + mDepthStencil.stencilBackMask = - 1; + mDepthStencil.stencilBackWritemask = -1; + mDepthStencil.stencilFail = GL_KEEP; + mDepthStencil.stencilPassDepthFail = GL_KEEP; + mDepthStencil.stencilPassDepthPass = GL_KEEP; + mDepthStencil.stencilBackFail = GL_KEEP; + mDepthStencil.stencilBackPassDepthFail = GL_KEEP; + mDepthStencil.stencilBackPassDepthPass = GL_KEEP; + + mStencilRef = 0; + mStencilBackRef = 0; + + mSampleCoverage = false; + mSampleCoverageValue = 1.0f; + mSampleCoverageInvert = false; + mGenerateMipmapHint = GL_DONT_CARE; + mFragmentShaderDerivativeHint = GL_DONT_CARE; + + mLineWidth = 1.0f; + + mViewport.x = 0; + mViewport.y = 0; + mViewport.width = 0; + mViewport.height = 0; + mNearZ = 0.0f; + mFarZ = 1.0f; + + mBlend.colorMaskRed = true; + mBlend.colorMaskGreen = true; + mBlend.colorMaskBlue = true; + mBlend.colorMaskAlpha = true; + + 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++) + { + mSamplers[textureUnit].set(NULL); + } + + mActiveSampler = 0; + + mActiveQueries[GL_ANY_SAMPLES_PASSED].set(NULL); + mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(NULL); + mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(NULL); + + mCurrentProgramId = 0; + mCurrentProgramBinary.set(NULL); + + mReadFramebuffer = NULL; + mDrawFramebuffer = NULL; +} + +State::~State() +{ + for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) + { + for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) + { + mSamplerTexture[type][sampler].set(NULL); + } + } + + const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; + for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++) + { + mVertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues); + } + + mArrayBuffer.set(NULL); + mRenderbuffer.set(NULL); + + mTransformFeedback.set(NULL); + + for (State::ActiveQueryMap::iterator i = mActiveQueries.begin(); i != mActiveQueries.end(); i++) + { + i->second.set(NULL); + } + + mGenericUniformBuffer.set(NULL); + for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++) + { + mUniformBuffers[i].set(NULL); + } + + mGenericTransformFeedbackBuffer.set(NULL); + for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + { + mTransformFeedbackBuffers[i].set(NULL); + } + + mCopyReadBuffer.set(NULL); + mCopyWriteBuffer.set(NULL); + + mPack.pixelBuffer.set(NULL); + mUnpack.pixelBuffer.set(NULL); +} + +const RasterizerState &State::getRasterizerState() const +{ + return mRasterizer; +} + +const BlendState &State::getBlendState() const +{ + return mBlend; +} + +const DepthStencilState &State::getDepthStencilState() const +{ + return mDepthStencil; +} + +void State::setClearColor(float red, float green, float blue, float alpha) +{ + mColorClearValue.red = red; + mColorClearValue.green = green; + mColorClearValue.blue = blue; + mColorClearValue.alpha = alpha; +} + +void State::setClearDepth(float depth) +{ + mDepthClearValue = depth; +} + +void State::setClearStencil(int stencil) +{ + mStencilClearValue = stencil; +} + +ClearParameters State::getClearParameters(GLbitfield mask) const +{ + ClearParameters clearParams = { 0 }; + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = false; + } + clearParams.colorFClearValue = mColorClearValue; + clearParams.colorClearType = GL_FLOAT; + clearParams.colorMaskRed = mBlend.colorMaskRed; + clearParams.colorMaskGreen = mBlend.colorMaskGreen; + clearParams.colorMaskBlue = mBlend.colorMaskBlue; + clearParams.colorMaskAlpha = mBlend.colorMaskAlpha; + clearParams.clearDepth = false; + clearParams.depthClearValue = mDepthClearValue; + clearParams.clearStencil = false; + clearParams.stencilClearValue = mStencilClearValue; + clearParams.stencilWriteMask = mDepthStencil.stencilWritemask; + clearParams.scissorEnabled = mScissorTest; + clearParams.scissor = mScissor; + + const Framebuffer *framebufferObject = getDrawFramebuffer(); + if (mask & GL_COLOR_BUFFER_BIT) + { + if (framebufferObject->hasEnabledColorAttachment()) + { + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + clearParams.clearColor[i] = true; + } + } + } + + if (mask & GL_DEPTH_BUFFER_BIT) + { + if (mDepthStencil.depthMask && framebufferObject->getDepthbuffer() != NULL) + { + clearParams.clearDepth = true; + } + } + + if (mask & GL_STENCIL_BUFFER_BIT) + { + if (framebufferObject->getStencilbuffer() != NULL) + { + rx::RenderTarget *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil(); + if (!depthStencil) + { + ERR("Depth stencil pointer unexpectedly null."); + ClearParameters nullClearParam = { 0 }; + return nullClearParam; + } + + if (GetStencilBits(depthStencil->getActualFormat()) > 0) + { + clearParams.clearStencil = true; + } + } + } + + return clearParams; +} + +void State::setColorMask(bool red, bool green, bool blue, bool alpha) +{ + mBlend.colorMaskRed = red; + mBlend.colorMaskGreen = green; + mBlend.colorMaskBlue = blue; + mBlend.colorMaskAlpha = alpha; +} + +void State::setDepthMask(bool mask) +{ + mDepthStencil.depthMask = mask; +} + +bool State::isRasterizerDiscardEnabled() const +{ + return mRasterizer.rasterizerDiscard; +} + +void State::setRasterizerDiscard(bool enabled) +{ + mRasterizer.rasterizerDiscard = enabled; +} + +bool State::isCullFaceEnabled() const +{ + return mRasterizer.cullFace; +} + +void State::setCullFace(bool enabled) +{ + mRasterizer.cullFace = enabled; +} + +void State::setCullMode(GLenum mode) +{ + mRasterizer.cullMode = mode; +} + +void State::setFrontFace(GLenum front) +{ + mRasterizer.frontFace = front; +} + +bool State::isDepthTestEnabled() const +{ + return mDepthStencil.depthTest; +} + +void State::setDepthTest(bool enabled) +{ + mDepthStencil.depthTest = enabled; +} + +void State::setDepthFunc(GLenum depthFunc) +{ + mDepthStencil.depthFunc = depthFunc; +} + +void State::setDepthRange(float zNear, float zFar) +{ + mNearZ = zNear; + mFarZ = zFar; +} + +void State::getDepthRange(float *zNear, float *zFar) const +{ + *zNear = mNearZ; + *zFar = mFarZ; +} + +bool State::isBlendEnabled() const +{ + return mBlend.blend; +} + +void State::setBlend(bool enabled) +{ + mBlend.blend = enabled; +} + +void State::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha) +{ + mBlend.sourceBlendRGB = sourceRGB; + mBlend.destBlendRGB = destRGB; + mBlend.sourceBlendAlpha = sourceAlpha; + mBlend.destBlendAlpha = destAlpha; +} + +void State::setBlendColor(float red, float green, float blue, float alpha) +{ + mBlendColor.red = red; + mBlendColor.green = green; + mBlendColor.blue = blue; + mBlendColor.alpha = alpha; +} + +void State::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation) +{ + mBlend.blendEquationRGB = rgbEquation; + mBlend.blendEquationAlpha = alphaEquation; +} + +const ColorF &State::getBlendColor() const +{ + return mBlendColor; +} + +bool State::isStencilTestEnabled() const +{ + return mDepthStencil.stencilTest; +} + +void State::setStencilTest(bool enabled) +{ + mDepthStencil.stencilTest = enabled; +} + +void State::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask) +{ + mDepthStencil.stencilFunc = stencilFunc; + mStencilRef = (stencilRef > 0) ? stencilRef : 0; + mDepthStencil.stencilMask = stencilMask; +} + +void State::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask) +{ + mDepthStencil.stencilBackFunc = stencilBackFunc; + mStencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0; + mDepthStencil.stencilBackMask = stencilBackMask; +} + +void State::setStencilWritemask(GLuint stencilWritemask) +{ + mDepthStencil.stencilWritemask = stencilWritemask; +} + +void State::setStencilBackWritemask(GLuint stencilBackWritemask) +{ + mDepthStencil.stencilBackWritemask = stencilBackWritemask; +} + +void State::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass) +{ + mDepthStencil.stencilFail = stencilFail; + mDepthStencil.stencilPassDepthFail = stencilPassDepthFail; + mDepthStencil.stencilPassDepthPass = stencilPassDepthPass; +} + +void State::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass) +{ + mDepthStencil.stencilBackFail = stencilBackFail; + mDepthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail; + mDepthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass; +} + +GLint State::getStencilRef() const +{ + return mStencilRef; +} + +GLint State::getStencilBackRef() const +{ + return mStencilBackRef; +} + +bool State::isPolygonOffsetFillEnabled() const +{ + return mRasterizer.polygonOffsetFill; +} + +void State::setPolygonOffsetFill(bool enabled) +{ + mRasterizer.polygonOffsetFill = enabled; +} + +void State::setPolygonOffsetParams(GLfloat factor, GLfloat units) +{ + // An application can pass NaN values here, so handle this gracefully + mRasterizer.polygonOffsetFactor = factor != factor ? 0.0f : factor; + mRasterizer.polygonOffsetUnits = units != units ? 0.0f : units; +} + +bool State::isSampleAlphaToCoverageEnabled() const +{ + return mBlend.sampleAlphaToCoverage; +} + +void State::setSampleAlphaToCoverage(bool enabled) +{ + mBlend.sampleAlphaToCoverage = enabled; +} + +bool State::isSampleCoverageEnabled() const +{ + return mSampleCoverage; +} + +void State::setSampleCoverage(bool enabled) +{ + mSampleCoverage = enabled; +} + +void State::setSampleCoverageParams(GLclampf value, bool invert) +{ + mSampleCoverageValue = value; + mSampleCoverageInvert = invert; +} + +void State::getSampleCoverageParams(GLclampf *value, bool *invert) +{ + ASSERT(value != NULL && invert != NULL); + + *value = mSampleCoverageValue; + *invert = mSampleCoverageInvert; +} + +bool State::isScissorTestEnabled() const +{ + return mScissorTest; +} + +void State::setScissorTest(bool enabled) +{ + mScissorTest = enabled; +} + +void State::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height) +{ + mScissor.x = x; + mScissor.y = y; + mScissor.width = width; + mScissor.height = height; +} + +const Rectangle &State::getScissor() const +{ + return mScissor; +} + +bool State::isDitherEnabled() const +{ + return mBlend.dither; +} + +void State::setDither(bool enabled) +{ + mBlend.dither = enabled; +} + +void State::setEnableFeature(GLenum feature, bool enabled) +{ + switch (feature) + { + case GL_CULL_FACE: setCullFace(enabled); break; + case GL_POLYGON_OFFSET_FILL: setPolygonOffsetFill(enabled); break; + case GL_SAMPLE_ALPHA_TO_COVERAGE: setSampleAlphaToCoverage(enabled); break; + case GL_SAMPLE_COVERAGE: setSampleCoverage(enabled); break; + case GL_SCISSOR_TEST: setScissorTest(enabled); break; + case GL_STENCIL_TEST: setStencilTest(enabled); break; + case GL_DEPTH_TEST: setDepthTest(enabled); break; + case GL_BLEND: setBlend(enabled); break; + case GL_DITHER: setDither(enabled); break; + case GL_PRIMITIVE_RESTART_FIXED_INDEX: UNIMPLEMENTED(); break; + case GL_RASTERIZER_DISCARD: setRasterizerDiscard(enabled); break; + default: UNREACHABLE(); + } +} + +bool State::getEnableFeature(GLenum feature) +{ + switch (feature) + { + case GL_CULL_FACE: return isCullFaceEnabled(); + case GL_POLYGON_OFFSET_FILL: return isPolygonOffsetFillEnabled(); + case GL_SAMPLE_ALPHA_TO_COVERAGE: return isSampleAlphaToCoverageEnabled(); + case GL_SAMPLE_COVERAGE: return isSampleCoverageEnabled(); + case GL_SCISSOR_TEST: return isScissorTestEnabled(); + case GL_STENCIL_TEST: return isStencilTestEnabled(); + case GL_DEPTH_TEST: return isDepthTestEnabled(); + case GL_BLEND: return isBlendEnabled(); + case GL_DITHER: return isDitherEnabled(); + case GL_PRIMITIVE_RESTART_FIXED_INDEX: UNIMPLEMENTED(); return false; + case GL_RASTERIZER_DISCARD: return isRasterizerDiscardEnabled(); + default: UNREACHABLE(); return false; + } +} + +void State::setLineWidth(GLfloat width) +{ + mLineWidth = width; +} + +void State::setGenerateMipmapHint(GLenum hint) +{ + mGenerateMipmapHint = hint; +} + +void State::setFragmentShaderDerivativeHint(GLenum hint) +{ + mFragmentShaderDerivativeHint = hint; + // TODO: Propagate the hint to shader translator so we can write + // ddx, ddx_coarse, or ddx_fine depending on the hint. + // Ignore for now. It is valid for implementations to ignore hint. +} + +void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) +{ + mViewport.x = x; + mViewport.y = y; + mViewport.width = width; + mViewport.height = height; +} + +const Rectangle &State::getViewport() const +{ + return mViewport; +} + +void State::setActiveSampler(unsigned int active) +{ + mActiveSampler = active; +} + +unsigned int State::getActiveSampler() const +{ + return mActiveSampler; +} + +void State::setSamplerTexture(TextureType type, Texture *texture) +{ + mSamplerTexture[type][mActiveSampler].set(texture); +} + +Texture *State::getSamplerTexture(unsigned int sampler, TextureType type) const +{ + GLuint texid = mSamplerTexture[type][sampler].id(); + + if (texid == 0) // Special case: 0 refers to default textures held by Context + { + return NULL; + } + + return mSamplerTexture[type][sampler].get(); +} + +GLuint State::getSamplerTextureId(unsigned int sampler, TextureType type) const +{ + return mSamplerTexture[type][sampler].id(); +} + +void State::detachTexture(GLuint texture) +{ + // Textures have a detach method on State rather than a simple + // removeBinding, because the zero/null texture objects are managed + // separately, and don't have to go through the Context's maps or + // the ResourceManager. + + // [OpenGL ES 2.0.24] section 3.8 page 84: + // If a texture object is deleted, it is as if all texture units which are bound to that texture object are + // rebound to texture object zero + + for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) + { + for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) + { + if (mSamplerTexture[type][sampler].id() == texture) + { + mSamplerTexture[type][sampler].set(NULL); + } + } + } + + // [OpenGL ES 2.0.24] section 4.4 page 112: + // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is + // as if Texture2DAttachment had been called, with a texture of 0, for each attachment point to which this + // image was attached in the currently bound framebuffer. + + if (mReadFramebuffer) + { + mReadFramebuffer->detachTexture(texture); + } + + if (mDrawFramebuffer) + { + mDrawFramebuffer->detachTexture(texture); + } +} + +void State::setSamplerBinding(GLuint textureUnit, Sampler *sampler) +{ + mSamplers[textureUnit].set(sampler); +} + +GLuint State::getSamplerId(GLuint textureUnit) const +{ + ASSERT(textureUnit < ArraySize(mSamplers)); + return mSamplers[textureUnit].id(); +} + +Sampler *State::getSampler(GLuint textureUnit) const +{ + return mSamplers[textureUnit].get(); +} + +void State::detachSampler(GLuint sampler) +{ + // [OpenGL ES 3.0.2] section 3.8.2 pages 123-124: + // If a sampler object that is currently bound to one or more texture units is + // deleted, it is as though BindSampler is called once for each texture unit to + // which the sampler is bound, with unit set to the texture unit and sampler set to zero. + for (unsigned int textureUnit = 0; textureUnit < ArraySize(mSamplers); textureUnit++) + { + if (mSamplers[textureUnit].id() == sampler) + { + mSamplers[textureUnit].set(NULL); + } + } +} + +void State::setRenderbufferBinding(Renderbuffer *renderbuffer) +{ + mRenderbuffer.set(renderbuffer); +} + +GLuint State::getRenderbufferId() const +{ + return mRenderbuffer.id(); +} + +Renderbuffer *State::getCurrentRenderbuffer() +{ + return mRenderbuffer.get(); +} + +void State::detachRenderbuffer(GLuint renderbuffer) +{ + // [OpenGL ES 2.0.24] section 4.4 page 109: + // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer + // had been executed with the target RENDERBUFFER and name of zero. + + if (mRenderbuffer.id() == renderbuffer) + { + mRenderbuffer.set(NULL); + } + + // [OpenGL ES 2.0.24] section 4.4 page 111: + // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer, + // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment + // point to which this image was attached in the currently bound framebuffer. + + Framebuffer *readFramebuffer = mReadFramebuffer; + Framebuffer *drawFramebuffer = mDrawFramebuffer; + + if (readFramebuffer) + { + readFramebuffer->detachRenderbuffer(renderbuffer); + } + + if (drawFramebuffer && drawFramebuffer != readFramebuffer) + { + drawFramebuffer->detachRenderbuffer(renderbuffer); + } + +} + +void State::setReadFramebufferBinding(Framebuffer *framebuffer) +{ + mReadFramebuffer = framebuffer; +} + +void State::setDrawFramebufferBinding(Framebuffer *framebuffer) +{ + mDrawFramebuffer = framebuffer; +} + +Framebuffer *State::getTargetFramebuffer(GLenum target) const +{ + switch (target) + { + case GL_READ_FRAMEBUFFER_ANGLE: return mReadFramebuffer; + case GL_DRAW_FRAMEBUFFER_ANGLE: + case GL_FRAMEBUFFER: return mDrawFramebuffer; + default: UNREACHABLE(); return NULL; + } +} + +Framebuffer *State::getReadFramebuffer() +{ + return mReadFramebuffer; +} + +Framebuffer *State::getDrawFramebuffer() +{ + return mDrawFramebuffer; +} + +const Framebuffer *State::getReadFramebuffer() const +{ + return mReadFramebuffer; +} + +const Framebuffer *State::getDrawFramebuffer() const +{ + return mDrawFramebuffer; +} + +bool State::removeReadFramebufferBinding(GLuint framebuffer) +{ + if (mReadFramebuffer->id() == framebuffer) + { + mReadFramebuffer = NULL; + return true; + } + + return false; +} + +bool State::removeDrawFramebufferBinding(GLuint framebuffer) +{ + if (mDrawFramebuffer->id() == framebuffer) + { + mDrawFramebuffer = NULL; + return true; + } + + return false; +} + +void State::setVertexArrayBinding(VertexArray *vertexArray) +{ + mVertexArray = vertexArray; +} + +GLuint State::getVertexArrayId() const +{ + ASSERT(mVertexArray != NULL); + return mVertexArray->id(); +} + +VertexArray *State::getVertexArray() const +{ + ASSERT(mVertexArray != NULL); + return mVertexArray; +} + +bool State::removeVertexArrayBinding(GLuint vertexArray) +{ + if (mVertexArray->id() == vertexArray) + { + mVertexArray = NULL; + return true; + } + + return false; +} + +void State::setCurrentProgram(GLuint programId, Program *newProgram) +{ + mCurrentProgramId = programId; // set new ID before trying to delete program binary; otherwise it will only be flagged for deletion + mCurrentProgramBinary.set(NULL); + + if (newProgram) + { + newProgram->addRef(); + mCurrentProgramBinary.set(newProgram->getProgramBinary()); + } +} + +void State::setCurrentProgramBinary(ProgramBinary *binary) +{ + mCurrentProgramBinary.set(binary); +} + +GLuint State::getCurrentProgramId() const +{ + return mCurrentProgramId; +} + +ProgramBinary *State::getCurrentProgramBinary() const +{ + return mCurrentProgramBinary.get(); +} + +void State::setTransformFeedbackBinding(TransformFeedback *transformFeedback) +{ + mTransformFeedback.set(transformFeedback); +} + +TransformFeedback *State::getCurrentTransformFeedback() const +{ + return mTransformFeedback.get(); +} + +void State::detachTransformFeedback(GLuint transformFeedback) +{ + if (mTransformFeedback.id() == transformFeedback) + { + mTransformFeedback.set(NULL); + } +} + +bool State::isQueryActive() const +{ + for (State::ActiveQueryMap::const_iterator i = mActiveQueries.begin(); + i != mActiveQueries.end(); i++) + { + if (i->second.get() != NULL) + { + return true; + } + } + + return false; +} + +void State::setActiveQuery(GLenum target, Query *query) +{ + mActiveQueries[target].set(query); +} + +GLuint State::getActiveQueryId(GLenum target) const +{ + const Query *query = getActiveQuery(target); + return (query ? query->id() : 0u); +} + +Query *State::getActiveQuery(GLenum target) const +{ + // All query types should already exist in the activeQueries map + ASSERT(mActiveQueries.find(target) != mActiveQueries.end()); + + return mActiveQueries.at(target).get(); +} + +void State::setArrayBufferBinding(Buffer *buffer) +{ + mArrayBuffer.set(buffer); +} + +GLuint State::getArrayBufferId() const +{ + return mArrayBuffer.id(); +} + +bool State::removeArrayBufferBinding(GLuint buffer) +{ + if (mArrayBuffer.id() == buffer) + { + mArrayBuffer.set(NULL); + return true; + } + + return false; +} + +void State::setGenericUniformBufferBinding(Buffer *buffer) +{ + mGenericUniformBuffer.set(buffer); +} + +void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size) +{ + mUniformBuffers[index].set(buffer, offset, size); +} + +GLuint State::getIndexedUniformBufferId(GLuint index) const +{ + ASSERT(index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS); + + return mUniformBuffers[index].id(); +} + +Buffer *State::getIndexedUniformBuffer(GLuint index) const +{ + ASSERT(index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS); + + return mUniformBuffers[index].get(); +} + +void State::setGenericTransformFeedbackBufferBinding(Buffer *buffer) +{ + mGenericTransformFeedbackBuffer.set(buffer); +} + +void State::setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size) +{ + mTransformFeedbackBuffers[index].set(buffer, offset, size); +} + +GLuint State::getIndexedTransformFeedbackBufferId(GLuint index) const +{ + ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); + + return mTransformFeedbackBuffers[index].id(); +} + +Buffer *State::getIndexedTransformFeedbackBuffer(GLuint index) const +{ + ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); + + return mTransformFeedbackBuffers[index].get(); +} + +GLuint State::getIndexedTransformFeedbackBufferOffset(GLuint index) const +{ + ASSERT(index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS); + + return mTransformFeedbackBuffers[index].getOffset(); +} + +void State::setCopyReadBufferBinding(Buffer *buffer) +{ + mCopyReadBuffer.set(buffer); +} + +void State::setCopyWriteBufferBinding(Buffer *buffer) +{ + mCopyWriteBuffer.set(buffer); +} + +void State::setPixelPackBufferBinding(Buffer *buffer) +{ + mPack.pixelBuffer.set(buffer); +} + +void State::setPixelUnpackBufferBinding(Buffer *buffer) +{ + mUnpack.pixelBuffer.set(buffer); +} + +Buffer *State::getTargetBuffer(GLenum target) const +{ + switch (target) + { + case GL_ARRAY_BUFFER: return mArrayBuffer.get(); + case GL_COPY_READ_BUFFER: return mCopyReadBuffer.get(); + case GL_COPY_WRITE_BUFFER: return mCopyWriteBuffer.get(); + case GL_ELEMENT_ARRAY_BUFFER: return getVertexArray()->getElementArrayBuffer(); + case GL_PIXEL_PACK_BUFFER: return mPack.pixelBuffer.get(); + case GL_PIXEL_UNPACK_BUFFER: return mUnpack.pixelBuffer.get(); + case GL_TRANSFORM_FEEDBACK_BUFFER: return mGenericTransformFeedbackBuffer.get(); + case GL_UNIFORM_BUFFER: return mGenericUniformBuffer.get(); + default: UNREACHABLE(); return NULL; + } +} + +void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) +{ + getVertexArray()->enableAttribute(attribNum, enabled); +} + +void State::setVertexAttribf(GLuint index, const GLfloat values[4]) +{ + ASSERT(index < gl::MAX_VERTEX_ATTRIBS); + mVertexAttribCurrentValues[index].setFloatValues(values); +} + +void State::setVertexAttribu(GLuint index, const GLuint values[4]) +{ + ASSERT(index < gl::MAX_VERTEX_ATTRIBS); + mVertexAttribCurrentValues[index].setUnsignedIntValues(values); +} + +void State::setVertexAttribi(GLuint index, const GLint values[4]) +{ + ASSERT(index < gl::MAX_VERTEX_ATTRIBS); + mVertexAttribCurrentValues[index].setIntValues(values); +} + +void State::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized, + bool pureInteger, GLsizei stride, const void *pointer) +{ + getVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer); +} + +const VertexAttribute &State::getVertexAttribState(unsigned int attribNum) const +{ + return getVertexArray()->getVertexAttribute(attribNum); +} + +const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const +{ + ASSERT(attribNum < MAX_VERTEX_ATTRIBS); + return mVertexAttribCurrentValues[attribNum]; +} + +const VertexAttribCurrentValueData *State::getVertexAttribCurrentValues() const +{ + return mVertexAttribCurrentValues; +} + +const void *State::getVertexAttribPointer(unsigned int attribNum) const +{ + return getVertexArray()->getVertexAttribute(attribNum).pointer; +} + +void State::setPackAlignment(GLint alignment) +{ + mPack.alignment = alignment; +} + +GLint State::getPackAlignment() const +{ + return mPack.alignment; +} + +void State::setPackReverseRowOrder(bool reverseRowOrder) +{ + mPack.reverseRowOrder = reverseRowOrder; +} + +bool State::getPackReverseRowOrder() const +{ + return mPack.reverseRowOrder; +} + +const PixelPackState &State::getPackState() const +{ + return mPack; +} + +void State::setUnpackAlignment(GLint alignment) +{ + mUnpack.alignment = alignment; +} + +GLint State::getUnpackAlignment() const +{ + return mUnpack.alignment; +} + +const PixelUnpackState &State::getUnpackState() const +{ + return mUnpack; +} + +void State::getBooleanv(GLenum pname, GLboolean *params) +{ + switch (pname) + { + case GL_SAMPLE_COVERAGE_INVERT: *params = mSampleCoverageInvert; break; + case GL_DEPTH_WRITEMASK: *params = mDepthStencil.depthMask; break; + case GL_COLOR_WRITEMASK: + params[0] = mBlend.colorMaskRed; + params[1] = mBlend.colorMaskGreen; + params[2] = mBlend.colorMaskBlue; + params[3] = mBlend.colorMaskAlpha; + break; + case GL_CULL_FACE: *params = mRasterizer.cullFace; break; + case GL_POLYGON_OFFSET_FILL: *params = mRasterizer.polygonOffsetFill; break; + case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mBlend.sampleAlphaToCoverage; break; + case GL_SAMPLE_COVERAGE: *params = mSampleCoverage; break; + case GL_SCISSOR_TEST: *params = mScissorTest; break; + case GL_STENCIL_TEST: *params = mDepthStencil.stencilTest; break; + case GL_DEPTH_TEST: *params = mDepthStencil.depthTest; break; + case GL_BLEND: *params = mBlend.blend; break; + case GL_DITHER: *params = mBlend.dither; break; + case GL_TRANSFORM_FEEDBACK_ACTIVE: *params = getCurrentTransformFeedback()->isStarted(); break; + case GL_TRANSFORM_FEEDBACK_PAUSED: *params = getCurrentTransformFeedback()->isPaused(); break; + default: + UNREACHABLE(); + break; + } +} + +void State::getFloatv(GLenum pname, GLfloat *params) +{ + // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation + // because it is stored as a float, despite the fact that the GL ES 2.0 spec names + // GetIntegerv as its native query function. As it would require conversion in any + // case, this should make no difference to the calling application. + switch (pname) + { + case GL_LINE_WIDTH: *params = mLineWidth; break; + case GL_SAMPLE_COVERAGE_VALUE: *params = mSampleCoverageValue; break; + case GL_DEPTH_CLEAR_VALUE: *params = mDepthClearValue; break; + case GL_POLYGON_OFFSET_FACTOR: *params = mRasterizer.polygonOffsetFactor; break; + case GL_POLYGON_OFFSET_UNITS: *params = mRasterizer.polygonOffsetUnits; break; + case GL_DEPTH_RANGE: + params[0] = mNearZ; + params[1] = mFarZ; + break; + case GL_COLOR_CLEAR_VALUE: + params[0] = mColorClearValue.red; + params[1] = mColorClearValue.green; + params[2] = mColorClearValue.blue; + params[3] = mColorClearValue.alpha; + break; + case GL_BLEND_COLOR: + params[0] = mBlendColor.red; + params[1] = mBlendColor.green; + params[2] = mBlendColor.blue; + params[3] = mBlendColor.alpha; + break; + default: + UNREACHABLE(); + break; + } +} + +void State::getIntegerv(GLenum pname, GLint *params) +{ + if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT) + { + unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT); + ASSERT(colorAttachment < mContext->getCaps().maxDrawBuffers); + Framebuffer *framebuffer = mDrawFramebuffer; + *params = framebuffer->getDrawBufferState(colorAttachment); + return; + } + + // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation + // because it is stored as a float, despite the fact that the GL ES 2.0 spec names + // GetIntegerv as its native query function. As it would require conversion in any + // case, this should make no difference to the calling application. You may find it in + // State::getFloatv. + switch (pname) + { + case GL_ARRAY_BUFFER_BINDING: *params = mArrayBuffer.id(); break; + case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = getVertexArray()->getElementArrayBufferId(); break; + //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE + case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mDrawFramebuffer->id(); break; + case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mReadFramebuffer->id(); break; + case GL_RENDERBUFFER_BINDING: *params = mRenderbuffer.id(); break; + case GL_VERTEX_ARRAY_BINDING: *params = mVertexArray->id(); break; + case GL_CURRENT_PROGRAM: *params = mCurrentProgramId; break; + case GL_PACK_ALIGNMENT: *params = mPack.alignment; break; + case GL_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mPack.reverseRowOrder; break; + case GL_UNPACK_ALIGNMENT: *params = mUnpack.alignment; break; + case GL_GENERATE_MIPMAP_HINT: *params = mGenerateMipmapHint; break; + case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mFragmentShaderDerivativeHint; break; + case GL_ACTIVE_TEXTURE: *params = (mActiveSampler + GL_TEXTURE0); break; + case GL_STENCIL_FUNC: *params = mDepthStencil.stencilFunc; break; + case GL_STENCIL_REF: *params = mStencilRef; break; + case GL_STENCIL_VALUE_MASK: *params = clampToInt(mDepthStencil.stencilMask); break; + case GL_STENCIL_BACK_FUNC: *params = mDepthStencil.stencilBackFunc; break; + case GL_STENCIL_BACK_REF: *params = mStencilBackRef; break; + case GL_STENCIL_BACK_VALUE_MASK: *params = clampToInt(mDepthStencil.stencilBackMask); break; + case GL_STENCIL_FAIL: *params = mDepthStencil.stencilFail; break; + case GL_STENCIL_PASS_DEPTH_FAIL: *params = mDepthStencil.stencilPassDepthFail; break; + case GL_STENCIL_PASS_DEPTH_PASS: *params = mDepthStencil.stencilPassDepthPass; break; + case GL_STENCIL_BACK_FAIL: *params = mDepthStencil.stencilBackFail; break; + case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mDepthStencil.stencilBackPassDepthFail; break; + case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mDepthStencil.stencilBackPassDepthPass; break; + case GL_DEPTH_FUNC: *params = mDepthStencil.depthFunc; break; + case GL_BLEND_SRC_RGB: *params = mBlend.sourceBlendRGB; break; + case GL_BLEND_SRC_ALPHA: *params = mBlend.sourceBlendAlpha; break; + case GL_BLEND_DST_RGB: *params = mBlend.destBlendRGB; break; + case GL_BLEND_DST_ALPHA: *params = mBlend.destBlendAlpha; break; + case GL_BLEND_EQUATION_RGB: *params = mBlend.blendEquationRGB; break; + case GL_BLEND_EQUATION_ALPHA: *params = mBlend.blendEquationAlpha; break; + case GL_STENCIL_WRITEMASK: *params = clampToInt(mDepthStencil.stencilWritemask); break; + case GL_STENCIL_BACK_WRITEMASK: *params = clampToInt(mDepthStencil.stencilBackWritemask); break; + case GL_STENCIL_CLEAR_VALUE: *params = mStencilClearValue; break; + case GL_SAMPLE_BUFFERS: + case GL_SAMPLES: + { + gl::Framebuffer *framebuffer = mDrawFramebuffer; + if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) + { + switch (pname) + { + case GL_SAMPLE_BUFFERS: + if (framebuffer->getSamples() != 0) + { + *params = 1; + } + else + { + *params = 0; + } + break; + case GL_SAMPLES: + *params = framebuffer->getSamples(); + break; + } + } + else + { + *params = 0; + } + } + break; + case GL_VIEWPORT: + params[0] = mViewport.x; + params[1] = mViewport.y; + params[2] = mViewport.width; + params[3] = mViewport.height; + break; + case GL_SCISSOR_BOX: + params[0] = mScissor.x; + params[1] = mScissor.y; + params[2] = mScissor.width; + params[3] = mScissor.height; + break; + case GL_CULL_FACE_MODE: *params = mRasterizer.cullMode; break; + case GL_FRONT_FACE: *params = mRasterizer.frontFace; break; + case GL_RED_BITS: + case GL_GREEN_BITS: + case GL_BLUE_BITS: + case GL_ALPHA_BITS: + { + gl::Framebuffer *framebuffer = getDrawFramebuffer(); + gl::FramebufferAttachment *colorbuffer = framebuffer->getFirstColorbuffer(); + + if (colorbuffer) + { + switch (pname) + { + case GL_RED_BITS: *params = colorbuffer->getRedSize(); break; + case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break; + case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break; + case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break; + } + } + else + { + *params = 0; + } + } + break; + case GL_DEPTH_BITS: + { + gl::Framebuffer *framebuffer = getDrawFramebuffer(); + gl::FramebufferAttachment *depthbuffer = framebuffer->getDepthbuffer(); + + if (depthbuffer) + { + *params = depthbuffer->getDepthSize(); + } + else + { + *params = 0; + } + } + break; + case GL_STENCIL_BITS: + { + gl::Framebuffer *framebuffer = getDrawFramebuffer(); + gl::FramebufferAttachment *stencilbuffer = framebuffer->getStencilbuffer(); + + if (stencilbuffer) + { + *params = stencilbuffer->getStencilSize(); + } + else + { + *params = 0; + } + } + break; + case GL_TEXTURE_BINDING_2D: + ASSERT(mActiveSampler < mContext->getMaximumCombinedTextureImageUnits()); + *params = mSamplerTexture[TEXTURE_2D][mActiveSampler].id(); + break; + case GL_TEXTURE_BINDING_CUBE_MAP: + ASSERT(mActiveSampler < mContext->getMaximumCombinedTextureImageUnits()); + *params = mSamplerTexture[TEXTURE_CUBE][mActiveSampler].id(); + break; + case GL_TEXTURE_BINDING_3D: + ASSERT(mActiveSampler < mContext->getMaximumCombinedTextureImageUnits()); + *params = mSamplerTexture[TEXTURE_3D][mActiveSampler].id(); + break; + case GL_TEXTURE_BINDING_2D_ARRAY: + ASSERT(mActiveSampler < mContext->getMaximumCombinedTextureImageUnits()); + *params = mSamplerTexture[TEXTURE_2D_ARRAY][mActiveSampler].id(); + break; + case GL_UNIFORM_BUFFER_BINDING: + *params = mGenericUniformBuffer.id(); + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + *params = mGenericTransformFeedbackBuffer.id(); + break; + case GL_COPY_READ_BUFFER_BINDING: + *params = mCopyReadBuffer.id(); + break; + case GL_COPY_WRITE_BUFFER_BINDING: + *params = mCopyWriteBuffer.id(); + break; + case GL_PIXEL_PACK_BUFFER_BINDING: + *params = mPack.pixelBuffer.id(); + break; + case GL_PIXEL_UNPACK_BUFFER_BINDING: + *params = mUnpack.pixelBuffer.id(); + break; + default: + UNREACHABLE(); + break; + } +} + +bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data) +{ + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: + if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) + { + *data = mTransformFeedbackBuffers[index].id(); + } + break; + case GL_UNIFORM_BUFFER_BINDING: + if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) + { + *data = mUniformBuffers[index].id(); + } + break; + default: + return false; + } + + return true; +} + +bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) +{ + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER_START: + if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) + { + *data = mTransformFeedbackBuffers[index].getOffset(); + } + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: + if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) + { + *data = mTransformFeedbackBuffers[index].getSize(); + } + break; + case GL_UNIFORM_BUFFER_START: + if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) + { + *data = mUniformBuffers[index].getOffset(); + } + break; + case GL_UNIFORM_BUFFER_SIZE: + if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) + { + *data = mUniformBuffers[index].getSize(); + } + break; + default: + return false; + } + + return true; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/State.h b/src/3rdparty/angle/src/libGLESv2/State.h new file mode 100644 index 0000000000..09be0b335d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/State.h @@ -0,0 +1,307 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// State.h: Defines the State class, encapsulating raw GL state + +#ifndef LIBGLESV2_STATE_H_ +#define LIBGLESV2_STATE_H_ + +#include "common/angleutils.h" +#include "common/RefCountObject.h" +#include "libGLESv2/angletypes.h" +#include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/Texture.h" +#include "libGLESv2/TransformFeedback.h" +#include "libGLESv2/Program.h" +#include "libGLESv2/Sampler.h" + +namespace gl +{ +class Query; +class VertexArray; +class Context; + +class State +{ + public: + State(); + ~State(); + + void setContext(Context *context) { mContext = context; } + + // State chunk getters + const RasterizerState &getRasterizerState() const; + const BlendState &getBlendState() const; + const DepthStencilState &getDepthStencilState() const; + + // Clear behavior setters & state parameter block generation function + void setClearColor(float red, float green, float blue, float alpha); + void setClearDepth(float depth); + void setClearStencil(int stencil); + ClearParameters getClearParameters(GLbitfield mask) const; + + // Write mask manipulation + void setColorMask(bool red, bool green, bool blue, bool alpha); + void setDepthMask(bool mask); + + // Discard toggle & query + bool isRasterizerDiscardEnabled() const; + void setRasterizerDiscard(bool enabled); + + // Face culling state manipulation + bool isCullFaceEnabled() const; + void setCullFace(bool enabled); + void setCullMode(GLenum mode); + void setFrontFace(GLenum front); + + // Depth test state manipulation + bool isDepthTestEnabled() const; + void setDepthTest(bool enabled); + void setDepthFunc(GLenum depthFunc); + void setDepthRange(float zNear, float zFar); + void getDepthRange(float *zNear, float *zFar) const; + + // Blend state manipulation + bool isBlendEnabled() const; + void setBlend(bool enabled); + void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha); + void setBlendColor(float red, float green, float blue, float alpha); + void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation); + const ColorF &getBlendColor() const; + + // Stencil state maniupulation + bool isStencilTestEnabled() const; + void setStencilTest(bool enabled); + void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask); + void setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask); + void setStencilWritemask(GLuint stencilWritemask); + void setStencilBackWritemask(GLuint stencilBackWritemask); + void setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass); + void setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass); + GLint getStencilRef() const; + GLint getStencilBackRef() const; + + // Depth bias/polygon offset state manipulation + bool isPolygonOffsetFillEnabled() const; + void setPolygonOffsetFill(bool enabled); + void setPolygonOffsetParams(GLfloat factor, GLfloat units); + + // Multisample coverage state manipulation + bool isSampleAlphaToCoverageEnabled() const; + void setSampleAlphaToCoverage(bool enabled); + bool isSampleCoverageEnabled() const; + void setSampleCoverage(bool enabled); + void setSampleCoverageParams(GLclampf value, bool invert); + void getSampleCoverageParams(GLclampf *value, bool *invert); + + // Scissor test state toggle & query + bool isScissorTestEnabled() const; + void setScissorTest(bool enabled); + void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height); + const Rectangle &getScissor() const; + + // Dither state toggle & query + bool isDitherEnabled() const; + void setDither(bool enabled); + + // Generic state toggle & query + void setEnableFeature(GLenum feature, bool enabled); + bool getEnableFeature(GLenum feature); + + // Line width state setter + void setLineWidth(GLfloat width); + + // Hint setters + void setGenerateMipmapHint(GLenum hint); + void setFragmentShaderDerivativeHint(GLenum hint); + + // Viewport state setter/getter + void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height); + const Rectangle &getViewport() const; + + // Texture binding & active texture unit manipulation + void setActiveSampler(unsigned int active); + unsigned int getActiveSampler() const; + void setSamplerTexture(TextureType type, Texture *texture); + Texture *getSamplerTexture(unsigned int sampler, TextureType type) const; + GLuint getSamplerTextureId(unsigned int sampler, TextureType type) const; + void detachTexture(GLuint texture); + + // Sampler object binding manipulation + void setSamplerBinding(GLuint textureUnit, Sampler *sampler); + GLuint getSamplerId(GLuint textureUnit) const; + Sampler *getSampler(GLuint textureUnit) const; + void detachSampler(GLuint sampler); + + // Renderbuffer binding manipulation + void setRenderbufferBinding(Renderbuffer *renderbuffer); + GLuint getRenderbufferId() const; + Renderbuffer *getCurrentRenderbuffer(); + void detachRenderbuffer(GLuint renderbuffer); + + // Framebuffer binding manipulation + void setReadFramebufferBinding(Framebuffer *framebuffer); + void setDrawFramebufferBinding(Framebuffer *framebuffer); + Framebuffer *getTargetFramebuffer(GLenum target) const; + Framebuffer *getReadFramebuffer(); + Framebuffer *getDrawFramebuffer(); + const Framebuffer *getReadFramebuffer() const; + const Framebuffer *getDrawFramebuffer() const; + bool removeReadFramebufferBinding(GLuint framebuffer); + bool removeDrawFramebufferBinding(GLuint framebuffer); + + // Vertex array object binding manipulation + void setVertexArrayBinding(VertexArray *vertexArray); + GLuint getVertexArrayId() const; + VertexArray *getVertexArray() const; + bool removeVertexArrayBinding(GLuint vertexArray); + + // Program binding manipulation + void setCurrentProgram(GLuint programId, Program *newProgram); + void setCurrentProgramBinary(ProgramBinary *binary); + GLuint getCurrentProgramId() const; + ProgramBinary *getCurrentProgramBinary() const; + + // Transform feedback object (not buffer) binding manipulation + void setTransformFeedbackBinding(TransformFeedback *transformFeedback); + TransformFeedback *getCurrentTransformFeedback() const; + void detachTransformFeedback(GLuint transformFeedback); + + // Query binding manipulation + bool isQueryActive() const; + void setActiveQuery(GLenum target, Query *query); + GLuint getActiveQueryId(GLenum target) const; + Query *getActiveQuery(GLenum target) const; + + //// Typed buffer binding point manipulation //// + // GL_ARRAY_BUFFER + void setArrayBufferBinding(Buffer *buffer); + GLuint getArrayBufferId() const; + bool removeArrayBufferBinding(GLuint buffer); + + // GL_UNIFORM_BUFFER - Both indexed and generic targets + void setGenericUniformBufferBinding(Buffer *buffer); + void setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size); + GLuint getIndexedUniformBufferId(GLuint index) const; + Buffer *getIndexedUniformBuffer(GLuint index) const; + + // GL_TRANSFORM_FEEDBACK_BUFFER - Both indexed and generic targets + void setGenericTransformFeedbackBufferBinding(Buffer *buffer); + void setIndexedTransformFeedbackBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size); + GLuint getIndexedTransformFeedbackBufferId(GLuint index) const; + Buffer *getIndexedTransformFeedbackBuffer(GLuint index) const; + GLuint getIndexedTransformFeedbackBufferOffset(GLuint index) const; + + // GL_COPY_[READ/WRITE]_BUFFER + void setCopyReadBufferBinding(Buffer *buffer); + void setCopyWriteBufferBinding(Buffer *buffer); + + // GL_PIXEL[PACK/UNPACK]_BUFFER + void setPixelPackBufferBinding(Buffer *buffer); + void setPixelUnpackBufferBinding(Buffer *buffer); + + // Retrieve typed buffer by target (non-indexed) + Buffer *getTargetBuffer(GLenum target) const; + + // Vertex attrib manipulation + void setEnableVertexAttribArray(unsigned int attribNum, bool enabled); + void setVertexAttribf(GLuint index, const GLfloat values[4]); + void setVertexAttribu(GLuint index, const GLuint values[4]); + void setVertexAttribi(GLuint index, const GLint values[4]); + void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, + bool normalized, bool pureInteger, GLsizei stride, const void *pointer); + const VertexAttribute &getVertexAttribState(unsigned int attribNum) const; + const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const; + const VertexAttribCurrentValueData *getVertexAttribCurrentValues() const; + const void *getVertexAttribPointer(unsigned int attribNum) const; + + // Pixel pack state manipulation + void setPackAlignment(GLint alignment); + GLint getPackAlignment() const; + void setPackReverseRowOrder(bool reverseRowOrder); + bool getPackReverseRowOrder() const; + const PixelPackState &getPackState() const; + + // Pixel unpack state manipulation + void setUnpackAlignment(GLint alignment); + GLint getUnpackAlignment() const; + const PixelUnpackState &getUnpackState() const; + + // State query functions + void getBooleanv(GLenum pname, GLboolean *params); + void getFloatv(GLenum pname, GLfloat *params); + void getIntegerv(GLenum pname, GLint *params); + bool getIndexedIntegerv(GLenum target, GLuint index, GLint *data); + bool getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data); + + private: + DISALLOW_COPY_AND_ASSIGN(State); + + Context *mContext; + + ColorF mColorClearValue; + GLclampf mDepthClearValue; + int mStencilClearValue; + + RasterizerState mRasterizer; + bool mScissorTest; + Rectangle mScissor; + + BlendState mBlend; + ColorF mBlendColor; + bool mSampleCoverage; + GLclampf mSampleCoverageValue; + bool mSampleCoverageInvert; + + DepthStencilState mDepthStencil; + GLint mStencilRef; + GLint mStencilBackRef; + + GLfloat mLineWidth; + + GLenum mGenerateMipmapHint; + GLenum mFragmentShaderDerivativeHint; + + Rectangle mViewport; + float mNearZ; + float mFarZ; + + unsigned int mActiveSampler; // Active texture unit selector - GL_TEXTURE0 + BindingPointer mArrayBuffer; + Framebuffer *mReadFramebuffer; + Framebuffer *mDrawFramebuffer; + BindingPointer mRenderbuffer; + GLuint mCurrentProgramId; + BindingPointer mCurrentProgramBinary; + + 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]; + + typedef std::map< GLenum, BindingPointer > ActiveQueryMap; + ActiveQueryMap mActiveQueries; + + BindingPointer mGenericUniformBuffer; + OffsetBindingPointer mUniformBuffers[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS]; + + BindingPointer mTransformFeedback; + BindingPointer mGenericTransformFeedbackBuffer; + OffsetBindingPointer mTransformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; + + BindingPointer mCopyReadBuffer; + BindingPointer mCopyWriteBuffer; + + PixelUnpackState mUnpack; + PixelPackState mPack; +}; + +} + +#endif // LIBGLESV2_STATE_H_ + diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp index 3257d05dd4..b0c0ee51bd 100644 --- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Texture.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" // -// Copyright (c) 2002-2013 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. // @@ -12,168 +12,49 @@ #include "libGLESv2/Texture.h" #include "libGLESv2/main.h" -#include "libGLESv2/mathutil.h" -#include "libGLESv2/utilities.h" -#if defined(ANGLE_ENABLE_D3D9) -# include "libGLESv2/renderer/d3d9/Blit.h" -#else -# define D3DFMT_UNKNOWN DXGI_FORMAT_UNKNOWN -#endif +#include "common/mathutil.h" +#include "common/utilities.h" +#include "libGLESv2/formatutils.h" #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/renderer/Image.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/TextureStorage.h" +#include "libGLESv2/renderer/d3d/TextureStorage.h" #include "libEGL/Surface.h" +#include "libGLESv2/renderer/RenderTarget.h" +#include "libGLESv2/renderer/TextureImpl.h" namespace gl { -Texture::Texture(rx::Renderer *renderer, GLuint id) : RefCountObject(id) +Texture::Texture(GLuint id, GLenum target) + : RefCountObject(id), + mUsage(GL_NONE), + mImmutable(false), + mTarget(target) { - mRenderer = renderer; - - mSamplerState.minFilter = GL_NEAREST_MIPMAP_LINEAR; - mSamplerState.magFilter = GL_LINEAR; - mSamplerState.wrapS = GL_REPEAT; - mSamplerState.wrapT = GL_REPEAT; - mSamplerState.maxAnisotropy = 1.0f; - mSamplerState.lodOffset = 0; - mUsage = GL_NONE; - - mDirtyImages = true; - - mImmutable = false; } Texture::~Texture() { } -// Returns true on successful filter state update (valid enum parameter) -bool Texture::setMinFilter(GLenum filter) -{ - switch (filter) - { - case GL_NEAREST: - case GL_LINEAR: - case GL_NEAREST_MIPMAP_NEAREST: - case GL_LINEAR_MIPMAP_NEAREST: - case GL_NEAREST_MIPMAP_LINEAR: - case GL_LINEAR_MIPMAP_LINEAR: - mSamplerState.minFilter = filter; - return true; - default: - return false; - } -} - -// Returns true on successful filter state update (valid enum parameter) -bool Texture::setMagFilter(GLenum filter) +GLenum Texture::getTarget() const { - switch (filter) - { - case GL_NEAREST: - case GL_LINEAR: - mSamplerState.magFilter = filter; - return true; - default: - return false; - } + return mTarget; } -// Returns true on successful wrap state update (valid enum parameter) -bool Texture::setWrapS(GLenum wrap) +void Texture::setUsage(GLenum usage) { - switch (wrap) - { - case GL_REPEAT: - case GL_CLAMP_TO_EDGE: - case GL_MIRRORED_REPEAT: - mSamplerState.wrapS = wrap; - return true; - default: - return false; - } + mUsage = usage; } -// Returns true on successful wrap state update (valid enum parameter) -bool Texture::setWrapT(GLenum wrap) -{ - switch (wrap) - { - case GL_REPEAT: - case GL_CLAMP_TO_EDGE: - case GL_MIRRORED_REPEAT: - mSamplerState.wrapT = wrap; - return true; - default: - return false; - } -} - -// Returns true on successful max anisotropy update (valid anisotropy value) -bool Texture::setMaxAnisotropy(float textureMaxAnisotropy, float contextMaxAnisotropy) -{ - textureMaxAnisotropy = std::min(textureMaxAnisotropy, contextMaxAnisotropy); - if (textureMaxAnisotropy < 1.0f) - { - return false; - } - - mSamplerState.maxAnisotropy = textureMaxAnisotropy; - - return true; -} - -// Returns true on successful usage state update (valid enum parameter) -bool Texture::setUsage(GLenum usage) -{ - switch (usage) - { - case GL_NONE: - case GL_FRAMEBUFFER_ATTACHMENT_ANGLE: - mUsage = usage; - return true; - default: - return false; - } -} - -GLenum Texture::getMinFilter() const -{ - return mSamplerState.minFilter; -} - -GLenum Texture::getMagFilter() const -{ - return mSamplerState.magFilter; -} - -GLenum Texture::getWrapS() const -{ - return mSamplerState.wrapS; -} - -GLenum Texture::getWrapT() const -{ - return mSamplerState.wrapT; -} - -float Texture::getMaxAnisotropy() const -{ - return mSamplerState.maxAnisotropy; -} - -int Texture::getLodOffset() -{ - rx::TextureStorageInterface *texture = getStorage(false); - return texture ? texture->getLodOffset() : 0; -} - -void Texture::getSamplerState(SamplerState *sampler) +void Texture::getSamplerStateWithNativeOffset(SamplerState *sampler) { *sampler = mSamplerState; - sampler->lodOffset = getLodOffset(); + + // Offset the effective base level by the texture storage's top level + rx::TextureStorageInterface *texture = getNativeTexture(); + int topLevel = texture ? texture->getTopLevel() : 0; + sampler->baseLevel = topLevel + mSamplerState.baseLevel; } GLenum Texture::getUsage() const @@ -181,179 +62,97 @@ GLenum Texture::getUsage() const return mUsage; } -bool Texture::isMipmapFiltered() const +GLint Texture::getBaseLevelWidth() const { - switch (mSamplerState.minFilter) - { - case GL_NEAREST: - case GL_LINEAR: - return false; - case GL_NEAREST_MIPMAP_NEAREST: - case GL_LINEAR_MIPMAP_NEAREST: - case GL_NEAREST_MIPMAP_LINEAR: - case GL_LINEAR_MIPMAP_LINEAR: - return true; - default: UNREACHABLE(); - return false; - } + const rx::Image *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getWidth() : 0); } -void Texture::setImage(GLint unpackAlignment, const void *pixels, rx::Image *image) +GLint Texture::getBaseLevelHeight() const { - if (pixels != NULL) - { - image->loadData(0, 0, image->getWidth(), image->getHeight(), unpackAlignment, pixels); - mDirtyImages = true; - } + const rx::Image *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getHeight() : 0); } -void Texture::setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image) +GLint Texture::getBaseLevelDepth() const { - if (pixels != NULL) - { - image->loadCompressedData(0, 0, image->getWidth(), image->getHeight(), pixels); - mDirtyImages = true; - } + const rx::Image *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getDepth() : 0); } -bool Texture::subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, rx::Image *image) +// Note: "base level image" is loosely defined to be any image from the base level, +// where in the base of 2D array textures and cube maps there are several. Don't use +// the base level image for anything except querying texture format and size. +GLenum Texture::getBaseLevelInternalFormat() const { - if (pixels != NULL) - { - image->loadData(xoffset, yoffset, width, height, unpackAlignment, pixels); - mDirtyImages = true; - } - - return true; -} - -bool Texture::subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image) -{ - if (pixels != NULL) - { - image->loadCompressedData(xoffset, yoffset, width, height, pixels); - mDirtyImages = true; - } - - return true; -} - -rx::TextureStorageInterface *Texture::getNativeTexture() -{ - // ensure the underlying texture is created - - rx::TextureStorageInterface *storage = getStorage(false); - if (storage) - { - updateTexture(); - } - - return storage; -} - -bool Texture::hasDirtyImages() const -{ - return mDirtyImages; -} - -void Texture::resetDirty() -{ - mDirtyImages = false; + const rx::Image *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getInternalFormat() : GL_NONE); } unsigned int Texture::getTextureSerial() { - rx::TextureStorageInterface *texture = getStorage(false); + rx::TextureStorageInterface *texture = getNativeTexture(); return texture ? texture->getTextureSerial() : 0; } -unsigned int Texture::getRenderTargetSerial(GLenum target) -{ - rx::TextureStorageInterface *texture = getStorage(true); - return texture ? texture->getRenderTargetSerial(target) : 0; -} - bool Texture::isImmutable() const { return mImmutable; } -GLint Texture::creationLevels(GLsizei width, GLsizei height) const +int Texture::immutableLevelCount() { - if ((isPow2(width) && isPow2(height)) || mRenderer->getNonPower2TextureSupport()) - { - return 0; // Maximum number of levels - } - else - { - // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps. - return 1; - } + return (mImmutable ? getNativeTexture()->getStorageInstance()->getLevelCount() : 0); } -GLint Texture::creationLevels(GLsizei size) const +int Texture::mipLevels() const { - return creationLevels(size, size); + return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1; } -Texture2D::Texture2D(rx::Renderer *renderer, GLuint id) : Texture(renderer, id) +Texture2D::Texture2D(rx::Texture2DImpl *impl, GLuint id) + : Texture(id, GL_TEXTURE_2D), + mTexture(impl) { - mTexStorage = NULL; mSurface = NULL; - mColorbufferProxy = NULL; - mProxyRefs = 0; - - for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) - { - mImageArray[i] = renderer->createImage(); - } } Texture2D::~Texture2D() { - mColorbufferProxy = NULL; + SafeDelete(mTexture); - delete mTexStorage; - mTexStorage = NULL; - if (mSurface) { mSurface->setBoundTexture(NULL); mSurface = NULL; } - - for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) - { - delete mImageArray[i]; - } } -// We need to maintain a count of references to renderbuffers acting as -// proxies for this texture, so that we do not attempt to use a pointer -// to a renderbuffer proxy which has been deleted. -void Texture2D::addProxyRef(const Renderbuffer *proxy) +rx::TextureStorageInterface *Texture2D::getNativeTexture() { - mProxyRefs++; + return mTexture->getNativeTexture(); } -void Texture2D::releaseProxy(const Renderbuffer *proxy) +void Texture2D::setUsage(GLenum usage) { - if (mProxyRefs > 0) - mProxyRefs--; + mUsage = usage; + mTexture->setUsage(usage); +} - if (mProxyRefs == 0) - mColorbufferProxy = NULL; +bool Texture2D::hasDirtyImages() const +{ + return mTexture->hasDirtyImages(); } -GLenum Texture2D::getTarget() const +void Texture2D::resetDirty() { - return GL_TEXTURE_2D; + mTexture->resetDirty(); } GLsizei Texture2D::getWidth(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getWidth(); + return mTexture->getImage(level)->getWidth(); else return 0; } @@ -361,7 +160,7 @@ GLsizei Texture2D::getWidth(GLint level) const GLsizei Texture2D::getHeight(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getHeight(); + return mTexture->getImage(level)->getHeight(); else return 0; } @@ -369,7 +168,7 @@ GLsizei Texture2D::getHeight(GLint level) const GLenum Texture2D::getInternalFormat(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getInternalFormat(); + return mTexture->getImage(level)->getInternalFormat(); else return GL_NONE; } @@ -377,63 +176,33 @@ GLenum Texture2D::getInternalFormat(GLint level) const GLenum Texture2D::getActualFormat(GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[level]->getActualFormat(); + return mTexture->getImage(level)->getActualFormat(); else - return D3DFMT_UNKNOWN; + return GL_NONE; } -void Texture2D::redefineImage(GLint level, GLint internalformat, GLsizei width, GLsizei height) +void Texture2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height) { releaseTexImage(); - // If there currently is a corresponding storage texture image, it has these parameters - const int storageWidth = std::max(1, mImageArray[0]->getWidth() >> level); - const int storageHeight = std::max(1, mImageArray[0]->getHeight() >> level); - const int storageFormat = mImageArray[0]->getInternalFormat(); - - mImageArray[level]->redefine(mRenderer, internalformat, width, height, false); - - if (mTexStorage) - { - const int storageLevels = mTexStorage->levelCount(); - - if ((level >= storageLevels && storageLevels != 0) || - width != storageWidth || - height != storageHeight || - internalformat != storageFormat) // Discard mismatched storage - { - for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mImageArray[i]->markDirty(); - } - - delete mTexStorage; - mTexStorage = NULL; - mDirtyImages = true; - } - } + mTexture->redefineImage(level, internalformat, width, height); } -void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +void Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - GLint internalformat = ConvertSizedInternalFormat(format, type); - redefineImage(level, internalformat, width, height); + GLenum sizedInternalFormat = IsSizedInternalFormat(internalFormat) ? internalFormat + : GetSizedInternalFormat(format, type); + redefineImage(level, sizedInternalFormat, width, height); - Texture::setImage(unpackAlignment, pixels, mImageArray[level]); + mTexture->setImage(level, width, height, internalFormat, format, type, unpack, pixels); } void Texture2D::bindTexImage(egl::Surface *surface) { releaseTexImage(); - GLint internalformat = surface->getFormat(); + mTexture->bindTexImage(surface); - mImageArray[0]->redefine(mRenderer, internalformat, surface->getWidth(), surface->getHeight(), true); - - delete mTexStorage; - mTexStorage = new rx::TextureStorageInterface2D(mRenderer, surface->getSwapChain()); - - mDirtyImages = true; mSurface = surface; mSurface->setBoundTexture(this); } @@ -445,16 +214,7 @@ void Texture2D::releaseTexImage() mSurface->setBoundTexture(NULL); mSurface = NULL; - if (mTexStorage) - { - delete mTexStorage; - mTexStorage = NULL; - } - - for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mImageArray[i]->redefine(mRenderer, GL_NONE, 0, 0, true); - } + mTexture->releaseTexImage(); } } @@ -463,495 +223,126 @@ void Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GL // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly redefineImage(level, format, width, height); - Texture::setCompressedImage(imageSize, pixels, mImageArray[level]); + mTexture->setCompressedImage(level, format, width, height, imageSize, pixels); } -void Texture2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - if (level < levelCount()) - { - rx::Image *image = mImageArray[level]; - if (image->updateSurface(mTexStorage, level, xoffset, yoffset, width, height)) - { - image->markClean(); - } - } -} - -void Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) -{ - if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, mImageArray[level])) - { - commitRect(level, xoffset, yoffset, width, height); - } + mTexture->subImage(level, xoffset, yoffset, width, height, format, type, unpack, pixels); } void Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) { - if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, mImageArray[level])) - { - commitRect(level, xoffset, yoffset, width, height); - } + mTexture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, pixels); } void Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - GLint internalformat = ConvertSizedInternalFormat(format, GL_UNSIGNED_BYTE); - redefineImage(level, internalformat, width, height); + GLenum sizedInternalFormat = IsSizedInternalFormat(format) ? format + : GetSizedInternalFormat(format, GL_UNSIGNED_BYTE); + redefineImage(level, sizedInternalFormat, width, height); - if (!mImageArray[level]->isRenderableFormat()) - { - mImageArray[level]->copy(0, 0, x, y, width, height, source); - mDirtyImages = true; - } - else - { - if (!mTexStorage || !mTexStorage->isRenderTarget()) - { - convertToRenderTarget(); - } - - mImageArray[level]->markClean(); - - if (width != 0 && height != 0 && level < levelCount()) - { - gl::Rectangle sourceRect; - sourceRect.x = x; - sourceRect.width = width; - sourceRect.y = y; - sourceRect.height = height; - - mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, level); - } - } + mTexture->copyImage(level, format, x, y, width, height, source); } -void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +void Texture2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - if (xoffset + width > mImageArray[level]->getWidth() || yoffset + height > mImageArray[level]->getHeight()) - { - return gl::error(GL_INVALID_VALUE); - } - - if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !isSamplerComplete())) - { - mImageArray[level]->copy(xoffset, yoffset, x, y, width, height, source); - mDirtyImages = true; - } - else - { - if (!mTexStorage || !mTexStorage->isRenderTarget()) - { - convertToRenderTarget(); - } - - updateTexture(); - - if (level < levelCount()) - { - gl::Rectangle sourceRect; - sourceRect.x = x; - sourceRect.width = width; - sourceRect.y = y; - sourceRect.height = height; - - mRenderer->copyImage(source, sourceRect, - gl::ExtractFormat(mImageArray[0]->getInternalFormat()), - xoffset, yoffset, mTexStorage, level); - } - } + mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source); } void Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { - delete mTexStorage; - mTexStorage = new rx::TextureStorageInterface2D(mRenderer, levels, internalformat, mUsage, false, width, height); mImmutable = true; - for (int level = 0; level < levels; level++) - { - mImageArray[level]->redefine(mRenderer, internalformat, width, height, true); - width = std::max(1, width >> 1); - height = std::max(1, height >> 1); - } - - for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - mImageArray[level]->redefine(mRenderer, GL_NONE, 0, 0, true); - } - - if (mTexStorage->isManaged()) - { - int levels = levelCount(); - - for (int level = 0; level < levels; level++) - { - mImageArray[level]->setManagedSurface(mTexStorage, level); - } - } + mTexture->storage(levels, internalformat, width, height); } // Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85. -bool Texture2D::isSamplerComplete() const +bool Texture2D::isSamplerComplete(const SamplerState &samplerState) const { - GLsizei width = mImageArray[0]->getWidth(); - GLsizei height = mImageArray[0]->getHeight(); - - if (width <= 0 || height <= 0) - { - return false; - } - - bool mipmapping = isMipmapFiltered(); - bool filtering, renderable; - - if ((IsFloat32Format(getInternalFormat(0)) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) || - (IsFloat16Format(getInternalFormat(0)) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable))) - { - if (mSamplerState.magFilter != GL_NEAREST || - (mSamplerState.minFilter != GL_NEAREST && mSamplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) - { - return false; - } - } - - bool npotSupport = mRenderer->getNonPower2TextureSupport(); - - if (!npotSupport) - { - if ((mSamplerState.wrapS != GL_CLAMP_TO_EDGE && !isPow2(width)) || - (mSamplerState.wrapT != GL_CLAMP_TO_EDGE && !isPow2(height))) - { - return false; - } - } - - if (mipmapping) - { - if (!npotSupport) - { - if (!isPow2(width) || !isPow2(height)) - { - return false; - } - } - - if (!isMipmapComplete()) - { - return false; - } - } - - return true; -} - -// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. -bool Texture2D::isMipmapComplete() const -{ - if (isImmutable()) - { - return true; - } - - GLsizei width = mImageArray[0]->getWidth(); - GLsizei height = mImageArray[0]->getHeight(); - - if (width <= 0 || height <= 0) - { - return false; - } - - int q = log2(std::max(width, height)); - - for (int level = 1; level <= q; level++) - { - if (mImageArray[level]->getInternalFormat() != mImageArray[0]->getInternalFormat()) - { - return false; - } - - if (mImageArray[level]->getWidth() != std::max(1, width >> level)) - { - return false; - } - - if (mImageArray[level]->getHeight() != std::max(1, height >> level)) - { - return false; - } - } - - return true; + return mTexture->isSamplerComplete(samplerState); } bool Texture2D::isCompressed(GLint level) const { - return IsCompressed(getInternalFormat(level)); + return IsFormatCompressed(getInternalFormat(level)); } bool Texture2D::isDepth(GLint level) const { - return IsDepthTexture(getInternalFormat(level)); -} - -// Constructs a native texture resource from the texture images -void Texture2D::createTexture() -{ - GLsizei width = mImageArray[0]->getWidth(); - GLsizei height = mImageArray[0]->getHeight(); - - if (!(width > 0 && height > 0)) - return; // do not attempt to create native textures for nonexistant data - - GLint levels = creationLevels(width, height); - GLenum internalformat = mImageArray[0]->getInternalFormat(); - - delete mTexStorage; - mTexStorage = new rx::TextureStorageInterface2D(mRenderer, levels, internalformat, mUsage, false, width, height); - - if (mTexStorage->isManaged()) - { - int levels = levelCount(); - - for (int level = 0; level < levels; level++) - { - mImageArray[level]->setManagedSurface(mTexStorage, level); - } - } - - mDirtyImages = true; -} - -void Texture2D::updateTexture() -{ - bool mipmapping = (isMipmapFiltered() && isMipmapComplete()); - - int levels = (mipmapping ? levelCount() : 1); - - for (int level = 0; level < levels; level++) - { - rx::Image *image = mImageArray[level]; - - if (image->isDirty()) - { - commitRect(level, 0, 0, mImageArray[level]->getWidth(), mImageArray[level]->getHeight()); - } - } -} - -void Texture2D::convertToRenderTarget() -{ - rx::TextureStorageInterface2D *newTexStorage = NULL; - - if (mImageArray[0]->getWidth() != 0 && mImageArray[0]->getHeight() != 0) - { - GLsizei width = mImageArray[0]->getWidth(); - GLsizei height = mImageArray[0]->getHeight(); - GLint levels = mTexStorage != NULL ? mTexStorage->levelCount() : creationLevels(width, height); - GLenum internalformat = mImageArray[0]->getInternalFormat(); - - newTexStorage = new rx::TextureStorageInterface2D(mRenderer, levels, internalformat, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true, width, height); - - if (mTexStorage != NULL) - { - if (!mRenderer->copyToRenderTarget(newTexStorage, mTexStorage)) - { - delete newTexStorage; - return gl::error(GL_OUT_OF_MEMORY); - } - } - } - - delete mTexStorage; - mTexStorage = newTexStorage; - - mDirtyImages = true; + return GetDepthBits(getInternalFormat(level)) > 0; } void Texture2D::generateMipmaps() { - if (!mRenderer->getNonPower2TextureSupport()) - { - if (!isPow2(mImageArray[0]->getWidth()) || !isPow2(mImageArray[0]->getHeight())) - { - return gl::error(GL_INVALID_OPERATION); - } - } - // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - unsigned int q = log2(std::max(mImageArray[0]->getWidth(), mImageArray[0]->getHeight())); - for (unsigned int i = 1; i <= q; i++) + int levelCount = mipLevels(); + for (int level = 1; level < levelCount; level++) { - redefineImage(i, mImageArray[0]->getInternalFormat(), - std::max(mImageArray[0]->getWidth() >> i, 1), - std::max(mImageArray[0]->getHeight() >> i, 1)); + redefineImage(level, getBaseLevelInternalFormat(), + std::max(getBaseLevelWidth() >> level, 1), + std::max(getBaseLevelHeight() >> level, 1)); } - if (mTexStorage && mTexStorage->isRenderTarget()) - { - for (unsigned int i = 1; i <= q; i++) - { - mTexStorage->generateMipmap(i); - - mImageArray[i]->markClean(); - } - } - else - { - for (unsigned int i = 1; i <= q; i++) - { - mRenderer->generateMipmap(mImageArray[i], mImageArray[i - 1]); - } - } + mTexture->generateMipmaps(); } -Renderbuffer *Texture2D::getRenderbuffer(GLenum target) +const rx::Image *Texture2D::getBaseLevelImage() const { - if (target != GL_TEXTURE_2D) - { - return gl::error(GL_INVALID_OPERATION, (Renderbuffer *)NULL); - } - - if (mColorbufferProxy == NULL) - { - mColorbufferProxy = new Renderbuffer(mRenderer, id(), new RenderbufferTexture2D(this, target)); - } - - return mColorbufferProxy; + return mTexture->getImage(0); } -rx::RenderTarget *Texture2D::getRenderTarget(GLenum target) +unsigned int Texture2D::getRenderTargetSerial(GLint level) { - ASSERT(target == GL_TEXTURE_2D); - - // ensure the underlying texture is created - if (getStorage(true) == NULL) - { - return NULL; - } - - updateTexture(); - - // ensure this is NOT a depth texture - if (isDepth(0)) - { - return NULL; - } - - return mTexStorage->getRenderTarget(); + return mTexture->getRenderTargetSerial(level); } -rx::RenderTarget *Texture2D::getDepthStencil(GLenum target) +rx::RenderTarget *Texture2D::getRenderTarget(GLint level) { - ASSERT(target == GL_TEXTURE_2D); - - // ensure the underlying texture is created - if (getStorage(true) == NULL) - { - return NULL; - } - - updateTexture(); - - // ensure this is actually a depth texture - if (!isDepth(0)) - { - return NULL; - } - return mTexStorage->getRenderTarget(); + return mTexture->getRenderTarget(level); } -int Texture2D::levelCount() +rx::RenderTarget *Texture2D::getDepthSencil(GLint level) { - return mTexStorage ? mTexStorage->levelCount() : 0; + return mTexture->getDepthSencil(level); } -rx::TextureStorageInterface *Texture2D::getStorage(bool renderTarget) +TextureCubeMap::TextureCubeMap(rx::TextureCubeImpl *impl, GLuint id) + : Texture(id, GL_TEXTURE_CUBE_MAP), + mTexture(impl) { - if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget())) - { - if (renderTarget) - { - convertToRenderTarget(); - } - else - { - createTexture(); - } - } - - return mTexStorage; } -TextureCubeMap::TextureCubeMap(rx::Renderer *renderer, GLuint id) : Texture(renderer, id) +TextureCubeMap::~TextureCubeMap() { - mTexStorage = NULL; - for (int i = 0; i < 6; i++) - { - mFaceProxies[i] = NULL; - mFaceProxyRefs[i] = 0; - - for (int j = 0; j < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) - { - mImageArray[i][j] = renderer->createImage(); - } - } + SafeDelete(mTexture); } -TextureCubeMap::~TextureCubeMap() +rx::TextureStorageInterface *TextureCubeMap::getNativeTexture() { - for (int i = 0; i < 6; i++) - { - mFaceProxies[i] = NULL; - - for (int j = 0; j < IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) - { - delete mImageArray[i][j]; - } - } - - delete mTexStorage; - mTexStorage = NULL; + return mTexture->getNativeTexture(); } -// We need to maintain a count of references to renderbuffers acting as -// proxies for this texture, so that the texture is not deleted while -// proxy references still exist. If the reference count drops to zero, -// we set our proxy pointer NULL, so that a new attempt at referencing -// will cause recreation. -void TextureCubeMap::addProxyRef(const Renderbuffer *proxy) +void TextureCubeMap::setUsage(GLenum usage) { - for (int i = 0; i < 6; i++) - { - if (mFaceProxies[i] == proxy) - mFaceProxyRefs[i]++; - } + mUsage = usage; + mTexture->setUsage(usage); } -void TextureCubeMap::releaseProxy(const Renderbuffer *proxy) +bool TextureCubeMap::hasDirtyImages() const { - for (int i = 0; i < 6; i++) - { - if (mFaceProxies[i] == proxy) - { - if (mFaceProxyRefs[i] > 0) - mFaceProxyRefs[i]--; - - if (mFaceProxyRefs[i] == 0) - mFaceProxies[i] = NULL; - } - } + return mTexture->hasDirtyImages(); } -GLenum TextureCubeMap::getTarget() const +void TextureCubeMap::resetDirty() { - return GL_TEXTURE_CUBE_MAP; + mTexture->resetDirty(); } GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[faceIndex(target)][level]->getWidth(); + return mTexture->getImage(target, level)->getWidth(); else return 0; } @@ -959,7 +350,7 @@ GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[faceIndex(target)][level]->getHeight(); + return mTexture->getImage(target, level)->getHeight(); else return 0; } @@ -967,7 +358,7 @@ GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[faceIndex(target)][level]->getInternalFormat(); + return mTexture->getImage(target, level)->getInternalFormat(); else return GL_NONE; } @@ -975,525 +366,393 @@ GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const { if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) - return mImageArray[faceIndex(target)][level]->getActualFormat(); + return mTexture->getImage(target, level)->getActualFormat(); else - return D3DFMT_UNKNOWN; + return GL_NONE; } -void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +void TextureCubeMap::setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - setImage(0, level, width, height, format, type, unpackAlignment, pixels); + mTexture->setImage(0, level, width, height, internalFormat, format, type, unpack, pixels); } -void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +void TextureCubeMap::setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - setImage(1, level, width, height, format, type, unpackAlignment, pixels); + mTexture->setImage(1, level, width, height, internalFormat, format, type, unpack, pixels); } -void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +void TextureCubeMap::setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - setImage(2, level, width, height, format, type, unpackAlignment, pixels); + mTexture->setImage(2, level, width, height, internalFormat, format, type, unpack, pixels); } -void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +void TextureCubeMap::setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - setImage(3, level, width, height, format, type, unpackAlignment, pixels); + mTexture->setImage(3, level, width, height, internalFormat, format, type, unpack, pixels); } -void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +void TextureCubeMap::setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - setImage(4, level, width, height, format, type, unpackAlignment, pixels); + mTexture->setImage(4, level, width, height, internalFormat, format, type, unpack, pixels); } -void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +void TextureCubeMap::setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels) { - setImage(5, level, width, height, format, type, unpackAlignment, pixels); + mTexture->setImage(5, level, width, height, internalFormat, format, type, unpack, pixels); } -void TextureCubeMap::setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) +void TextureCubeMap::setCompressedImage(GLenum target, 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(faceIndex(face), level, format, width, height); + mTexture->setCompressedImage(target, level, format, width, height, imageSize, pixels); +} - Texture::setCompressedImage(imageSize, pixels, mImageArray[faceIndex(face)][level]); +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); } -void TextureCubeMap::commitRect(int face, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) { - if (level < levelCount()) - { - rx::Image *image = mImageArray[face][level]; - if (image->updateSurface(mTexStorage, face, level, xoffset, yoffset, width, height)) - image->markClean(); - } + mTexture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, pixels); } -void TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +// Tests for cube map sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 86. +bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState) const { - if (Texture::subImage(xoffset, yoffset, width, height, format, type, unpackAlignment, pixels, mImageArray[faceIndex(target)][level])) - { - commitRect(faceIndex(target), level, xoffset, yoffset, width, height); - } + return mTexture->isSamplerComplete(samplerState); } -void TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels) +// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. +bool TextureCubeMap::isCubeComplete() const { - if (Texture::subImageCompressed(xoffset, yoffset, width, height, format, imageSize, pixels, mImageArray[faceIndex(target)][level])) - { - commitRect(faceIndex(target), level, xoffset, yoffset, width, height); - } + return mTexture->isCubeComplete(); } -// Tests for cube map sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 86. -bool TextureCubeMap::isSamplerComplete() const +bool TextureCubeMap::isCompressed(GLenum target, GLint level) const { - int size = mImageArray[0][0]->getWidth(); + return IsFormatCompressed(getInternalFormat(target, level)); +} - bool mipmapping = isMipmapFiltered(); - bool filtering, renderable; +bool TextureCubeMap::isDepth(GLenum target, GLint level) const +{ + return GetDepthBits(getInternalFormat(target, level)) > 0; +} - if ((gl::ExtractType(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)) == GL_FLOAT && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) || - (gl::ExtractType(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0) == GL_HALF_FLOAT_OES) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable))) - { - if (mSamplerState.magFilter != GL_NEAREST || - (mSamplerState.minFilter != GL_NEAREST && mSamplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST)) - { - return false; - } - } +void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +{ + mTexture->copyImage(target, level, format, x, y, width, height, source); +} - if (!isPow2(size) && !mRenderer->getNonPower2TextureSupport()) - { - if (mSamplerState.wrapS != GL_CLAMP_TO_EDGE || mSamplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping) - { - return false; - } - } +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); +} - if (!mipmapping) - { - if (!isCubeComplete()) - { - return false; - } - } - else - { - if (!isMipmapCubeComplete()) // Also tests for isCubeComplete() - { - return false; - } - } +void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size) +{ + mImmutable = true; - return true; + mTexture->storage(levels, internalformat, size); } -// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. -bool TextureCubeMap::isCubeComplete() const +void TextureCubeMap::generateMipmaps() { - if (mImageArray[0][0]->getWidth() <= 0 || mImageArray[0][0]->getHeight() != mImageArray[0][0]->getWidth()) - { - return false; - } + mTexture->generateMipmaps(); +} - for (unsigned int face = 1; face < 6; face++) - { - if (mImageArray[face][0]->getWidth() != mImageArray[0][0]->getWidth() || - mImageArray[face][0]->getWidth() != mImageArray[0][0]->getHeight() || - mImageArray[face][0]->getInternalFormat() != mImageArray[0][0]->getInternalFormat()) - { - return false; - } - } +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); +} - return true; +unsigned int TextureCubeMap::getRenderTargetSerial(GLenum target, GLint level) +{ + return mTexture->getRenderTargetSerial(target, level); } -bool TextureCubeMap::isMipmapCubeComplete() const +rx::RenderTarget *TextureCubeMap::getRenderTarget(GLenum target, GLint level) { - if (isImmutable()) - { - return true; - } + return mTexture->getRenderTarget(target, level); +} - if (!isCubeComplete()) - { - return false; - } +rx::RenderTarget *TextureCubeMap::getDepthStencil(GLenum target, GLint level) +{ + return mTexture->getDepthStencil(target, level); +} - GLsizei size = mImageArray[0][0]->getWidth(); +Texture3D::Texture3D(rx::Texture3DImpl *impl, GLuint id) + : Texture(id, GL_TEXTURE_3D), + mTexture(impl) +{ +} - int q = log2(size); +Texture3D::~Texture3D() +{ + SafeDelete(mTexture); +} - for (int face = 0; face < 6; face++) - { - for (int level = 1; level <= q; level++) - { - if (mImageArray[face][level]->getInternalFormat() != mImageArray[0][0]->getInternalFormat()) - { - return false; - } - - if (mImageArray[face][level]->getWidth() != std::max(1, size >> level)) - { - return false; - } - } - } +rx::TextureStorageInterface *Texture3D::getNativeTexture() +{ + return mTexture->getNativeTexture(); +} - return true; +void Texture3D::setUsage(GLenum usage) +{ + mUsage = usage; + mTexture->setUsage(usage); } -bool TextureCubeMap::isCompressed(GLenum target, GLint level) const +bool Texture3D::hasDirtyImages() const { - return IsCompressed(getInternalFormat(target, level)); + return mTexture->hasDirtyImages(); } -// Constructs a native texture resource from the texture images, or returns an existing one -void TextureCubeMap::createTexture() +void Texture3D::resetDirty() { - GLsizei size = mImageArray[0][0]->getWidth(); + mTexture->resetDirty(); +} - if (!(size > 0)) - return; // do not attempt to create native textures for nonexistant data +GLsizei Texture3D::getWidth(GLint level) const +{ + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level)->getWidth() : 0; +} - GLint levels = creationLevels(size); - GLenum internalformat = mImageArray[0][0]->getInternalFormat(); +GLsizei Texture3D::getHeight(GLint level) const +{ + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level)->getHeight() : 0; +} - delete mTexStorage; - mTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, mUsage, false, size); +GLsizei Texture3D::getDepth(GLint level) const +{ + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level)->getDepth() : 0; +} - if (mTexStorage->isManaged()) - { - int levels = levelCount(); - - for (int face = 0; face < 6; face++) - { - for (int level = 0; level < levels; level++) - { - mImageArray[face][level]->setManagedSurface(mTexStorage, face, level); - } - } - } +GLenum Texture3D::getInternalFormat(GLint level) const +{ + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level)->getInternalFormat() : GL_NONE; +} - mDirtyImages = true; +GLenum Texture3D::getActualFormat(GLint level) const +{ + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level)->getActualFormat() : GL_NONE; } -void TextureCubeMap::updateTexture() +bool Texture3D::isCompressed(GLint level) const { - bool mipmapping = isMipmapFiltered() && isMipmapCubeComplete(); + return IsFormatCompressed(getInternalFormat(level)); +} - for (int face = 0; face < 6; face++) - { - int levels = (mipmapping ? levelCount() : 1); +bool Texture3D::isDepth(GLint level) const +{ + return GetDepthBits(getInternalFormat(level)) > 0; +} - for (int level = 0; level < levels; level++) - { - rx::Image *image = mImageArray[face][level]; +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); +} - if (image->isDirty()) - { - commitRect(face, level, 0, 0, image->getWidth(), image->getHeight()); - } - } - } +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); } -void TextureCubeMap::convertToRenderTarget() +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) { - rx::TextureStorageInterfaceCube *newTexStorage = NULL; + mTexture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels); +} - if (mImageArray[0][0]->getWidth() != 0) - { - GLsizei size = mImageArray[0][0]->getWidth(); - GLint levels = mTexStorage != NULL ? mTexStorage->levelCount() : creationLevels(size); - GLenum internalformat = mImageArray[0][0]->getInternalFormat(); - - newTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, GL_FRAMEBUFFER_ATTACHMENT_ANGLE, true, size); - - if (mTexStorage != NULL) - { - if (!mRenderer->copyToRenderTarget(newTexStorage, mTexStorage)) - { - delete newTexStorage; - return gl::error(GL_OUT_OF_MEMORY); - } - } - } +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); +} - delete mTexStorage; - mTexStorage = newTexStorage; +void Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + mImmutable = true; - mDirtyImages = true; + mTexture->storage(levels, internalformat, width, height, depth); } -void TextureCubeMap::setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels) +void Texture3D::generateMipmaps() { - GLint internalformat = ConvertSizedInternalFormat(format, type); - redefineImage(faceIndex, level, internalformat, width, height); + mTexture->generateMipmaps(); +} - Texture::setImage(unpackAlignment, pixels, mImageArray[faceIndex][level]); +const rx::Image *Texture3D::getBaseLevelImage() const +{ + return mTexture->getImage(0); } -unsigned int TextureCubeMap::faceIndex(GLenum face) +void Texture3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) { - 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); + mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source); +} - return face - GL_TEXTURE_CUBE_MAP_POSITIVE_X; +bool Texture3D::isSamplerComplete(const SamplerState &samplerState) const +{ + return mTexture->isSamplerComplete(samplerState); } -void TextureCubeMap::redefineImage(int face, GLint level, GLint internalformat, GLsizei width, GLsizei height) +bool Texture3D::isMipmapComplete() const { - // If there currently is a corresponding storage texture image, it has these parameters - const int storageWidth = std::max(1, mImageArray[0][0]->getWidth() >> level); - const int storageHeight = std::max(1, mImageArray[0][0]->getHeight() >> level); - const int storageFormat = mImageArray[0][0]->getInternalFormat(); + return mTexture->isMipmapComplete(); +} - mImageArray[face][level]->redefine(mRenderer, internalformat, width, height, false); +unsigned int Texture3D::getRenderTargetSerial(GLint level, GLint layer) +{ + return mTexture->getRenderTargetSerial(level, layer); +} - if (mTexStorage) - { - const int storageLevels = mTexStorage->levelCount(); - - if ((level >= storageLevels && storageLevels != 0) || - width != storageWidth || - height != storageHeight || - internalformat != storageFormat) // Discard mismatched storage - { - for (int i = 0; i < IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - for (int f = 0; f < 6; f++) - { - mImageArray[f][i]->markDirty(); - } - } - - delete mTexStorage; - mTexStorage = NULL; - - mDirtyImages = true; - } - } +rx::RenderTarget *Texture3D::getRenderTarget(GLint level) +{ + return mTexture->getRenderTarget(level); } -void TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +rx::RenderTarget *Texture3D::getRenderTarget(GLint level, GLint layer) { - unsigned int faceindex = faceIndex(target); - GLint internalformat = gl::ConvertSizedInternalFormat(format, GL_UNSIGNED_BYTE); - redefineImage(faceindex, level, internalformat, width, height); + return mTexture->getRenderTarget(level, layer); +} - if (!mImageArray[faceindex][level]->isRenderableFormat()) - { - mImageArray[faceindex][level]->copy(0, 0, x, y, width, height, source); - mDirtyImages = true; - } - else - { - if (!mTexStorage || !mTexStorage->isRenderTarget()) - { - convertToRenderTarget(); - } - - mImageArray[faceindex][level]->markClean(); - - ASSERT(width == height); - - if (width > 0 && level < levelCount()) - { - gl::Rectangle sourceRect; - sourceRect.x = x; - sourceRect.width = width; - sourceRect.y = y; - sourceRect.height = height; - - mRenderer->copyImage(source, sourceRect, format, 0, 0, mTexStorage, target, level); - } - } +rx::RenderTarget *Texture3D::getDepthStencil(GLint level, GLint layer) +{ + return mTexture->getDepthStencil(level, layer); } -void TextureCubeMap::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) +Texture2DArray::Texture2DArray(rx::Texture2DArrayImpl *impl, GLuint id) + : Texture(id, GL_TEXTURE_2D_ARRAY), + mTexture(impl) { - GLsizei size = mImageArray[faceIndex(target)][level]->getWidth(); +} - if (xoffset + width > size || yoffset + height > size) - { - return gl::error(GL_INVALID_VALUE); - } +Texture2DArray::~Texture2DArray() +{ + SafeDelete(mTexture); +} - unsigned int faceindex = faceIndex(target); +rx::TextureStorageInterface *Texture2DArray::getNativeTexture() +{ + return mTexture->getNativeTexture(); +} - if (!mImageArray[faceindex][level]->isRenderableFormat() || (!mTexStorage && !isSamplerComplete())) - { - mImageArray[faceindex][level]->copy(0, 0, x, y, width, height, source); - mDirtyImages = true; - } - else - { - if (!mTexStorage || !mTexStorage->isRenderTarget()) - { - convertToRenderTarget(); - } - - updateTexture(); - - if (level < levelCount()) - { - gl::Rectangle sourceRect; - sourceRect.x = x; - sourceRect.width = width; - sourceRect.y = y; - sourceRect.height = height; - - mRenderer->copyImage(source, sourceRect, gl::ExtractFormat(mImageArray[0][0]->getInternalFormat()), - xoffset, yoffset, mTexStorage, target, level); - } - } +void Texture2DArray::setUsage(GLenum usage) +{ + mUsage = usage; + mTexture->setUsage(usage); } -void TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size) +bool Texture2DArray::hasDirtyImages() const { - delete mTexStorage; - mTexStorage = new rx::TextureStorageInterfaceCube(mRenderer, levels, internalformat, mUsage, false, size); - mImmutable = true; + return mTexture->hasDirtyImages(); +} - for (int level = 0; level < levels; level++) - { - GLsizei mipSize = std::max(1, size >> level); - for (int face = 0; face < 6; face++) - { - mImageArray[face][level]->redefine(mRenderer, internalformat, mipSize, mipSize, true); - } - } +void Texture2DArray::resetDirty() +{ + mTexture->resetDirty(); +} - for (int level = levels; level < IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) - { - for (int face = 0; face < 6; face++) - { - mImageArray[face][level]->redefine(mRenderer, GL_NONE, 0, 0, true); - } - } +GLsizei Texture2DArray::getWidth(GLint level) const +{ + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getWidth() : 0; +} - if (mTexStorage->isManaged()) - { - int levels = levelCount(); - - for (int face = 0; face < 6; face++) - { - for (int level = 0; level < levels; level++) - { - mImageArray[face][level]->setManagedSurface(mTexStorage, face, level); - } - } - } +GLsizei Texture2DArray::getHeight(GLint level) const +{ + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getHeight() : 0; } -void TextureCubeMap::generateMipmaps() +GLsizei Texture2DArray::getLayers(GLint level) const { - if (!isCubeComplete()) - { - return gl::error(GL_INVALID_OPERATION); - } + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getLayerCount(level) : 0; +} - if (!mRenderer->getNonPower2TextureSupport()) - { - if (!isPow2(mImageArray[0][0]->getWidth())) - { - return gl::error(GL_INVALID_OPERATION); - } - } +GLenum Texture2DArray::getInternalFormat(GLint level) const +{ + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE; +} - // Purge array levels 1 through q and reset them to represent the generated mipmap levels. - unsigned int q = log2(mImageArray[0][0]->getWidth()); - for (unsigned int f = 0; f < 6; f++) - { - for (unsigned int i = 1; i <= q; i++) - { - redefineImage(f, i, mImageArray[f][0]->getInternalFormat(), - std::max(mImageArray[f][0]->getWidth() >> i, 1), - std::max(mImageArray[f][0]->getWidth() >> i, 1)); - } - } +GLenum Texture2DArray::getActualFormat(GLint level) const +{ + return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getActualFormat() : GL_NONE; +} - if (mTexStorage && mTexStorage->isRenderTarget()) - { - for (unsigned int f = 0; f < 6; f++) - { - for (unsigned int i = 1; i <= q; i++) - { - mTexStorage->generateMipmap(f, i); - - mImageArray[f][i]->markClean(); - } - } - } - else - { - for (unsigned int f = 0; f < 6; f++) - { - for (unsigned int i = 1; i <= q; i++) - { - mRenderer->generateMipmap(mImageArray[f][i], mImageArray[f][i - 1]); - } - } - } +bool Texture2DArray::isCompressed(GLint level) const +{ + return IsFormatCompressed(getInternalFormat(level)); } -Renderbuffer *TextureCubeMap::getRenderbuffer(GLenum target) +bool Texture2DArray::isDepth(GLint level) const { - if (!IsCubemapTextureTarget(target)) - { - return gl::error(GL_INVALID_OPERATION, (Renderbuffer *)NULL); - } + return GetDepthBits(getInternalFormat(level)) > 0; +} - unsigned int face = faceIndex(target); +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); +} - if (mFaceProxies[face] == NULL) - { - mFaceProxies[face] = new Renderbuffer(mRenderer, id(), new RenderbufferTextureCubeMap(this, target)); - } +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); +} - return mFaceProxies[face]; +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); } -rx::RenderTarget *TextureCubeMap::getRenderTarget(GLenum target) +void Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const void *pixels) { - ASSERT(IsCubemapTextureTarget(target)); + mTexture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, pixels); +} - // ensure the underlying texture is created - if (getStorage(true) == NULL) - { - return NULL; - } +void Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + mImmutable = true; - updateTexture(); - - return mTexStorage->getRenderTarget(target); + mTexture->storage(levels, internalformat, width, height, depth); } -int TextureCubeMap::levelCount() +void Texture2DArray::generateMipmaps() { - return mTexStorage ? mTexStorage->levelCount() - getLodOffset() : 0; + mTexture->generateMipmaps(); } -rx::TextureStorageInterface *TextureCubeMap::getStorage(bool renderTarget) +const rx::Image *Texture2DArray::getBaseLevelImage() const { - if (!mTexStorage || (renderTarget && !mTexStorage->isRenderTarget())) - { - if (renderTarget) - { - convertToRenderTarget(); - } - else - { - createTexture(); - } - } + return (mTexture->getLayerCount(0) > 0 ? mTexture->getImage(0, 0) : NULL); +} + +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); +} - return mTexStorage; +bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState) const +{ + return mTexture->isSamplerComplete(samplerState); +} + +bool Texture2DArray::isMipmapComplete() const +{ + return mTexture->isMipmapComplete(); +} + +unsigned int Texture2DArray::getRenderTargetSerial(GLint level, GLint layer) +{ + return mTexture->getRenderTargetSerial(level, layer); +} + +rx::RenderTarget *Texture2DArray::getRenderTarget(GLint level, GLint layer) +{ + return mTexture->getRenderTarget(level, layer); +} + +rx::RenderTarget *Texture2DArray::getDepthStencil(GLint level, GLint layer) +{ + return mTexture->getDepthStencil(level, layer); } } diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.h b/src/3rdparty/angle/src/libGLESv2/Texture.h index 4f5fab28d0..29f952f9f6 100644 --- a/src/3rdparty/angle/src/libGLESv2/Texture.h +++ b/src/3rdparty/angle/src/libGLESv2/Texture.h @@ -13,12 +13,12 @@ #include -#define GL_APICALL -#include +#include "angle_gl.h" #include "common/debug.h" #include "common/RefCountObject.h" #include "libGLESv2/angletypes.h" +#include "libGLESv2/constants.h" namespace egl { @@ -27,10 +27,11 @@ class Surface; namespace rx { -class Renderer; +class Texture2DImpl; +class TextureCubeImpl; +class Texture3DImpl; +class Texture2DArrayImpl; class TextureStorageInterface; -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; class RenderTarget; class Image; } @@ -38,108 +39,72 @@ class Image; namespace gl { class Framebuffer; -class Renderbuffer; - -enum -{ - // These are the maximums the implementation can support - // The actual GL caps are limited by the device caps - // and should be queried from the Context - IMPLEMENTATION_MAX_TEXTURE_SIZE = 16384, - IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384, - - IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE -}; +class FramebufferAttachment; class Texture : public RefCountObject { public: - Texture(rx::Renderer *renderer, GLuint id); + Texture(GLuint id, GLenum target); virtual ~Texture(); - virtual void addProxyRef(const Renderbuffer *proxy) = 0; - virtual void releaseProxy(const Renderbuffer *proxy) = 0; - - virtual GLenum getTarget() const = 0; - - bool setMinFilter(GLenum filter); - bool setMagFilter(GLenum filter); - bool setWrapS(GLenum wrap); - bool setWrapT(GLenum wrap); - bool setMaxAnisotropy(float textureMaxAnisotropy, float contextMaxAnisotropy); - bool setUsage(GLenum usage); - - GLenum getMinFilter() const; - GLenum getMagFilter() const; - GLenum getWrapS() const; - GLenum getWrapT() const; - float getMaxAnisotropy() const; - int getLodOffset(); - void getSamplerState(SamplerState *sampler); + GLenum getTarget() const; + + const SamplerState &getSamplerState() const { return mSamplerState; } + SamplerState &getSamplerState() { return mSamplerState; } + void getSamplerStateWithNativeOffset(SamplerState *sampler); + + virtual void setUsage(GLenum usage); GLenum getUsage() const; - bool isMipmapFiltered() const; - virtual bool isSamplerComplete() const = 0; + GLint getBaseLevelWidth() const; + GLint getBaseLevelHeight() const; + GLint getBaseLevelDepth() const; + GLenum getBaseLevelInternalFormat() const; + + virtual bool isSamplerComplete(const SamplerState &samplerState) const = 0; - rx::TextureStorageInterface *getNativeTexture(); - virtual Renderbuffer *getRenderbuffer(GLenum target) = 0; + virtual rx::TextureStorageInterface *getNativeTexture() = 0; virtual void generateMipmaps() = 0; - virtual void copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source) = 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; - bool hasDirtyParameters() const; - bool hasDirtyImages() const; - void resetDirty(); + virtual bool hasDirtyImages() const = 0; + virtual void resetDirty() = 0; unsigned int getTextureSerial(); - unsigned int getRenderTargetSerial(GLenum target); bool isImmutable() const; + int immutableLevelCount(); static const GLuint INCOMPLETE_TEXTURE_ID = static_cast(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager. protected: - void setImage(GLint unpackAlignment, const void *pixels, rx::Image *image); - bool subImage(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels, rx::Image *image); - void setCompressedImage(GLsizei imageSize, const void *pixels, rx::Image *image); - bool subImageCompressed(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const void *pixels, rx::Image *image); - - GLint creationLevels(GLsizei width, GLsizei height) const; - GLint creationLevels(GLsizei size) const; - - virtual void createTexture() = 0; - virtual void updateTexture() = 0; - virtual void convertToRenderTarget() = 0; - virtual rx::RenderTarget *getRenderTarget(GLenum target) = 0; - - virtual int levelCount() = 0; - - rx::Renderer *mRenderer; + int mipLevels() const; SamplerState mSamplerState; GLenum mUsage; - bool mDirtyImages; - bool mImmutable; + GLenum mTarget; + private: DISALLOW_COPY_AND_ASSIGN(Texture); - virtual rx::TextureStorageInterface *getStorage(bool renderTarget) = 0; + virtual const rx::Image *getBaseLevelImage() const = 0; }; class Texture2D : public Texture { public: - Texture2D(rx::Renderer *renderer, GLuint id); + Texture2D(rx::Texture2DImpl *impl, GLuint id); ~Texture2D(); - void addProxyRef(const Renderbuffer *proxy); - void releaseProxy(const Renderbuffer *proxy); - - virtual GLenum getTarget() const; + virtual rx::TextureStorageInterface *getNativeTexture(); + virtual void setUsage(GLenum usage); + virtual bool hasDirtyImages() const; + virtual void resetDirty(); GLsizei getWidth(GLint level) const; GLsizei getHeight(GLint level) const; @@ -148,128 +113,187 @@ class Texture2D : public Texture bool isCompressed(GLint level) const; bool isDepth(GLint level) const; - void setImage(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); + void setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); - void subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); + 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 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; + virtual bool isSamplerComplete(const SamplerState &samplerState) const; virtual void bindTexImage(egl::Surface *surface); virtual void releaseTexImage(); virtual void generateMipmaps(); - virtual Renderbuffer *getRenderbuffer(GLenum target); + unsigned int getRenderTargetSerial(GLint level); protected: - friend class RenderbufferTexture2D; - virtual rx::RenderTarget *getRenderTarget(GLenum target); - virtual rx::RenderTarget *getDepthStencil(GLenum target); - virtual int levelCount(); + friend class Texture2DAttachment; + rx::RenderTarget *getRenderTarget(GLint level); + rx::RenderTarget *getDepthSencil(GLint level); private: DISALLOW_COPY_AND_ASSIGN(Texture2D); - virtual void createTexture(); - virtual void updateTexture(); - virtual void convertToRenderTarget(); - virtual rx::TextureStorageInterface *getStorage(bool renderTarget); - - bool isMipmapComplete() const; + virtual const rx::Image *getBaseLevelImage() const; - void redefineImage(GLint level, GLint internalformat, GLsizei width, GLsizei height); - void commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height); - rx::Image *mImageArray[IMPLEMENTATION_MAX_TEXTURE_LEVELS]; - - rx::TextureStorageInterface2D *mTexStorage; + rx::Texture2DImpl *mTexture; egl::Surface *mSurface; - - // A specific internal reference count is kept for colorbuffer proxy references, - // because, as the renderbuffer acting as proxy will maintain a binding pointer - // back to this texture, there would be a circular reference if we used a binding - // pointer here. This reference count will cause the pointer to be set to NULL if - // the count drops to zero, but will not cause deletion of the Renderbuffer. - Renderbuffer *mColorbufferProxy; - unsigned int mProxyRefs; }; class TextureCubeMap : public Texture { public: - TextureCubeMap(rx::Renderer *renderer, GLuint id); + TextureCubeMap(rx::TextureCubeImpl *impl, GLuint id); ~TextureCubeMap(); - void addProxyRef(const Renderbuffer *proxy); - void releaseProxy(const Renderbuffer *proxy); + virtual rx::TextureStorageInterface *getNativeTexture(); + virtual void setUsage(GLenum usage); + virtual bool hasDirtyImages() const; + virtual void resetDirty(); - virtual GLenum getTarget() const; - GLsizei getWidth(GLenum target, GLint level) const; GLsizei getHeight(GLenum target, GLint level) const; GLenum getInternalFormat(GLenum target, GLint level) const; GLenum getActualFormat(GLenum target, GLint level) const; bool isCompressed(GLenum target, GLint level) const; + bool isDepth(GLenum target, GLint level) const; - void setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); - void setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); - void setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); - void setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); - void setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); - void setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); + void setImagePosX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + void setImageNegX(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + void setImagePosY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + void setImageNegY(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + void setImagePosZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + void setImageNegZ(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); - void setCompressedImage(GLenum face, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); + void setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels); - void subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); + 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 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; + virtual bool isSamplerComplete(const SamplerState &samplerState) const; + bool isCubeComplete() const; virtual void generateMipmaps(); - virtual Renderbuffer *getRenderbuffer(GLenum target); - - static unsigned int faceIndex(GLenum face); + unsigned int getRenderTargetSerial(GLenum target, GLint level); protected: - friend class RenderbufferTextureCubeMap; - virtual rx::RenderTarget *getRenderTarget(GLenum target); - virtual int levelCount(); + friend class TextureCubeMapAttachment; + rx::RenderTarget *getRenderTarget(GLenum target, GLint level); + rx::RenderTarget *getDepthStencil(GLenum target, GLint level); private: DISALLOW_COPY_AND_ASSIGN(TextureCubeMap); - virtual void createTexture(); - virtual void updateTexture(); - virtual void convertToRenderTarget(); - virtual rx::TextureStorageInterface *getStorage(bool renderTarget); + virtual const rx::Image *getBaseLevelImage() const; - bool isCubeComplete() const; - bool isMipmapCubeComplete() const; + rx::TextureCubeImpl *mTexture; +}; + +class Texture3D : public Texture +{ + public: + Texture3D(rx::Texture3DImpl *impl, GLuint id); + + ~Texture3D(); - void setImage(int faceIndex, GLint level, GLsizei width, GLsizei height, GLenum format, GLenum type, GLint unpackAlignment, const void *pixels); - void commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - void redefineImage(int faceIndex, GLint level, GLint internalformat, GLsizei width, GLsizei height); + virtual rx::TextureStorageInterface *getNativeTexture(); + virtual void setUsage(GLenum usage); + virtual bool hasDirtyImages() const; + virtual void resetDirty(); - rx::Image *mImageArray[6][IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + GLsizei getWidth(GLint level) const; + GLsizei getHeight(GLint level) const; + GLsizei getDepth(GLint level) const; + GLenum getInternalFormat(GLint level) const; + GLenum getActualFormat(GLint level) const; + bool isCompressed(GLint level) const; + bool isDepth(GLint level) const; - rx::TextureStorageInterfaceCube *mTexStorage; + void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); + void 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); + 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); - // A specific internal reference count is kept for colorbuffer proxy references, - // because, as the renderbuffer acting as proxy will maintain a binding pointer - // back to this texture, there would be a circular reference if we used a binding - // pointer here. This reference count will cause the pointer to be set to NULL if - // the count drops to zero, but will not cause deletion of the Renderbuffer. - Renderbuffer *mFaceProxies[6]; - unsigned int *mFaceProxyRefs[6]; + 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); + + private: + DISALLOW_COPY_AND_ASSIGN(Texture3D); + + virtual const rx::Image *getBaseLevelImage() const; + + rx::Texture3DImpl *mTexture; +}; + +class Texture2DArray : public Texture +{ + public: + Texture2DArray(rx::Texture2DArrayImpl *impl, GLuint id); + + ~Texture2DArray(); + + virtual rx::TextureStorageInterface *getNativeTexture(); + virtual void setUsage(GLenum usage); + virtual bool hasDirtyImages() const; + virtual void resetDirty(); + + GLsizei getWidth(GLint level) const; + GLsizei getHeight(GLint level) const; + GLsizei getLayers(GLint level) const; + GLenum getInternalFormat(GLint level) const; + GLenum getActualFormat(GLint level) const; + bool isCompressed(GLint level) const; + bool isDepth(GLint level) const; + + void setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels); + void setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const void *pixels); + void 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); + 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); + + private: + DISALLOW_COPY_AND_ASSIGN(Texture2DArray); + + virtual const rx::Image *getBaseLevelImage() const; + + rx::Texture2DArrayImpl *mTexture; }; + } #endif // LIBGLESV2_TEXTURE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp b/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp new file mode 100644 index 0000000000..79ce08405d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp @@ -0,0 +1,63 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "libGLESv2/TransformFeedback.h" + +namespace gl +{ + +TransformFeedback::TransformFeedback(GLuint id) + : RefCountObject(id), + mStarted(GL_FALSE), + mPrimitiveMode(GL_NONE), + mPaused(GL_FALSE) +{ +} + +TransformFeedback::~TransformFeedback() +{ +} + +void TransformFeedback::start(GLenum primitiveMode) +{ + mStarted = GL_TRUE; + mPrimitiveMode = primitiveMode; + mPaused = GL_FALSE; +} + +void TransformFeedback::stop() +{ + mStarted = GL_FALSE; + mPrimitiveMode = GL_NONE; + mPaused = GL_FALSE; +} + +GLboolean TransformFeedback::isStarted() const +{ + return mStarted; +} + +GLenum TransformFeedback::getDrawMode() const +{ + return mPrimitiveMode; +} + +void TransformFeedback::pause() +{ + mPaused = GL_TRUE; +} + +void TransformFeedback::resume() +{ + mPaused = GL_FALSE; +} + +GLboolean TransformFeedback::isPaused() const +{ + return mPaused; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h b/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h new file mode 100644 index 0000000000..d6f4522e2a --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h @@ -0,0 +1,44 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef LIBGLESV2_TRANSFORM_FEEDBACK_H_ +#define LIBGLESV2_TRANSFORM_FEEDBACK_H_ + +#include "common/angleutils.h" +#include "common/RefCountObject.h" + +#include "angle_gl.h" + +namespace gl +{ + +class TransformFeedback : public RefCountObject +{ + public: + explicit TransformFeedback(GLuint id); + virtual ~TransformFeedback(); + + void start(GLenum primitiveMode); + void stop(); + GLboolean isStarted() const; + + GLenum getDrawMode() const; + + void pause(); + void resume(); + GLboolean isPaused() const; + + private: + DISALLOW_COPY_AND_ASSIGN(TransformFeedback); + + GLboolean mStarted; + GLenum mPrimitiveMode; + GLboolean mPaused; +}; + +} + +#endif // LIBGLESV2_TRANSFORM_FEEDBACK_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/Uniform.cpp b/src/3rdparty/angle/src/libGLESv2/Uniform.cpp index 5424e271b5..cddc7ec7d0 100644 --- a/src/3rdparty/angle/src/libGLESv2/Uniform.cpp +++ b/src/3rdparty/angle/src/libGLESv2/Uniform.cpp @@ -7,37 +7,100 @@ #include "libGLESv2/Uniform.h" -#include "libGLESv2/utilities.h" +#include "common/utilities.h" namespace gl { -Uniform::Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize) - : type(type), precision(precision), name(name), arraySize(arraySize) +LinkedUniform::LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, + const int blockIndex, const sh::BlockMemberInfo &blockInfo) + : type(type), + precision(precision), + name(name), + arraySize(arraySize), + blockIndex(blockIndex), + blockInfo(blockInfo), + data(NULL), + dirty(true), + psRegisterIndex(GL_INVALID_INDEX), + vsRegisterIndex(GL_INVALID_INDEX), + registerCount(0), + registerElement(0) { - int bytes = gl::UniformInternalSize(type) * elementCount(); - data = new unsigned char[bytes]; - memset(data, 0, bytes); - dirty = true; - - psRegisterIndex = -1; - vsRegisterIndex = -1; - registerCount = VariableRowCount(type) * elementCount(); + // We use data storage for default block uniforms to cache values that are sent to D3D during rendering + // Uniform blocks/buffers are treated separately by the Renderer (ES3 path only) + if (isInDefaultBlock()) + { + size_t bytes = dataSize(); + data = new unsigned char[bytes]; + memset(data, 0, bytes); + registerCount = VariableRowCount(type) * elementCount(); + } } -Uniform::~Uniform() +LinkedUniform::~LinkedUniform() { delete[] data; } -bool Uniform::isArray() const +bool LinkedUniform::isArray() const { return arraySize > 0; } -unsigned int Uniform::elementCount() const +unsigned int LinkedUniform::elementCount() const { return arraySize > 0 ? arraySize : 1; } +bool LinkedUniform::isReferencedByVertexShader() const +{ + return vsRegisterIndex != GL_INVALID_INDEX; +} + +bool LinkedUniform::isReferencedByFragmentShader() const +{ + return psRegisterIndex != GL_INVALID_INDEX; +} + +bool LinkedUniform::isInDefaultBlock() const +{ + return blockIndex == -1; +} + +size_t LinkedUniform::dataSize() const +{ + ASSERT(type != GL_STRUCT_ANGLEX); + return VariableInternalSize(type) * elementCount(); +} + +bool LinkedUniform::isSampler() const +{ + return IsSampler(type); +} + +UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize) + : name(name), + elementIndex(elementIndex), + dataSize(dataSize), + psRegisterIndex(GL_INVALID_INDEX), + vsRegisterIndex(GL_INVALID_INDEX) +{ +} + +bool UniformBlock::isArrayElement() const +{ + return elementIndex != GL_INVALID_INDEX; +} + +bool UniformBlock::isReferencedByVertexShader() const +{ + return vsRegisterIndex != GL_INVALID_INDEX; +} + +bool UniformBlock::isReferencedByFragmentShader() const +{ + return psRegisterIndex != GL_INVALID_INDEX; +} + } diff --git a/src/3rdparty/angle/src/libGLESv2/Uniform.h b/src/3rdparty/angle/src/libGLESv2/Uniform.h index 8ab0fbe234..24f834f3c6 100644 --- a/src/3rdparty/angle/src/libGLESv2/Uniform.h +++ b/src/3rdparty/angle/src/libGLESv2/Uniform.h @@ -10,38 +10,69 @@ #include #include -#define GL_APICALL -#include +#include "angle_gl.h" #include "common/debug.h" +#include "angletypes.h" +#include "common/shadervars.h" +#include "common/blocklayout.h" namespace gl { // Helper struct representing a single shader uniform -struct Uniform +struct LinkedUniform { - Uniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize); + LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, const int blockIndex, const sh::BlockMemberInfo &blockInfo); - ~Uniform(); + ~LinkedUniform(); bool isArray() const; unsigned int elementCount() const; + bool isReferencedByVertexShader() const; + bool isReferencedByFragmentShader() const; + bool isInDefaultBlock() const; + size_t dataSize() const; + bool isSampler() const; const GLenum type; const GLenum precision; const std::string name; const unsigned int arraySize; + const int blockIndex; + const sh::BlockMemberInfo blockInfo; unsigned char *data; bool dirty; - int psRegisterIndex; - int vsRegisterIndex; + unsigned int psRegisterIndex; + unsigned int vsRegisterIndex; unsigned int registerCount; + + // Register "elements" are used for uniform structs in ES3, to appropriately identify single uniforms + // inside aggregate types, which are packed according C-like structure rules. + unsigned int registerElement; }; -typedef std::vector UniformArray; +// Helper struct representing a single shader uniform block +struct UniformBlock +{ + // use GL_INVALID_INDEX for non-array elements + UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize); + + bool isArrayElement() const; + bool isReferencedByVertexShader() const; + bool isReferencedByFragmentShader() const; + + const std::string name; + const unsigned int elementIndex; + const unsigned int dataSize; + + std::vector memberUniformIndexes; + + unsigned int psRegisterIndex; + unsigned int vsRegisterIndex; +}; } diff --git a/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp b/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp new file mode 100644 index 0000000000..120064a532 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp @@ -0,0 +1,97 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Implementation of the state class for mananging GLES 3 Vertex Array Objects. +// + +#include "libGLESv2/VertexArray.h" +#include "libGLESv2/Buffer.h" +#include "libGLESv2/renderer/VertexArrayImpl.h" + +namespace gl +{ + +VertexArray::VertexArray(rx::VertexArrayImpl *impl, GLuint id, size_t maxAttribs) + : mId(id), + mVertexArray(impl), + mVertexAttributes(maxAttribs) +{ + ASSERT(impl != NULL); +} + +VertexArray::~VertexArray() +{ + SafeDelete(mVertexArray); + + for (size_t i = 0; i < getMaxAttribs(); i++) + { + mVertexAttributes[i].buffer.set(NULL); + } + mElementArrayBuffer.set(NULL); +} + +GLuint VertexArray::id() const +{ + return mId; +} + +void VertexArray::detachBuffer(GLuint bufferName) +{ + for (size_t attribute = 0; attribute < getMaxAttribs(); attribute++) + { + if (mVertexAttributes[attribute].buffer.id() == bufferName) + { + mVertexAttributes[attribute].buffer.set(NULL); + } + } + + if (mElementArrayBuffer.id() == bufferName) + { + mElementArrayBuffer.set(NULL); + } +} + +const VertexAttribute& VertexArray::getVertexAttribute(size_t attributeIndex) const +{ + ASSERT(attributeIndex < getMaxAttribs()); + return mVertexAttributes[attributeIndex]; +} + +void VertexArray::setVertexAttribDivisor(GLuint index, GLuint divisor) +{ + ASSERT(index < getMaxAttribs()); + mVertexAttributes[index].divisor = divisor; + mVertexArray->setAttributeDivisor(index, divisor); +} + +void VertexArray::enableAttribute(unsigned int attributeIndex, bool enabledState) +{ + ASSERT(attributeIndex < getMaxAttribs()); + mVertexAttributes[attributeIndex].enabled = enabledState; + mVertexArray->enableAttribute(attributeIndex, enabledState); +} + +void VertexArray::setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type, + bool normalized, bool pureInteger, GLsizei stride, const void *pointer) +{ + ASSERT(attributeIndex < getMaxAttribs()); + mVertexAttributes[attributeIndex].buffer.set(boundBuffer); + mVertexAttributes[attributeIndex].size = size; + mVertexAttributes[attributeIndex].type = type; + mVertexAttributes[attributeIndex].normalized = normalized; + mVertexAttributes[attributeIndex].pureInteger = pureInteger; + mVertexAttributes[attributeIndex].stride = stride; + mVertexAttributes[attributeIndex].pointer = pointer; + mVertexArray->setAttribute(attributeIndex, mVertexAttributes[attributeIndex]); +} + +void VertexArray::setElementArrayBuffer(Buffer *buffer) +{ + mElementArrayBuffer.set(buffer); + mVertexArray->setElementArrayBuffer(buffer); +} + +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/VertexArray.h b/src/3rdparty/angle/src/libGLESv2/VertexArray.h new file mode 100644 index 0000000000..accd98731a --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/VertexArray.h @@ -0,0 +1,61 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// This class contains prototypes for representing GLES 3 Vertex Array Objects: +// +// The buffer objects that are to be used by the vertex stage of the GL are collected +// together to form a vertex array object. All state related to the definition of data used +// by the vertex processor is encapsulated in a vertex array object. +// + +#ifndef LIBGLESV2_VERTEXARRAY_H_ +#define LIBGLESV2_VERTEXARRAY_H_ + +#include "common/RefCountObject.h" +#include "libGLESv2/constants.h" +#include "libGLESv2/VertexAttribute.h" + +namespace rx +{ +class Renderer; +class VertexArrayImpl; +} + +namespace gl +{ +class Buffer; + +class VertexArray +{ + public: + VertexArray(rx::VertexArrayImpl *impl, GLuint id, size_t maxAttribs); + ~VertexArray(); + + GLuint id() const; + + const VertexAttribute& getVertexAttribute(size_t attributeIndex) const; + void detachBuffer(GLuint bufferName); + void setVertexAttribDivisor(GLuint index, GLuint divisor); + void enableAttribute(unsigned int attributeIndex, bool enabledState); + void setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type, + bool normalized, bool pureInteger, GLsizei stride, const void *pointer); + + const VertexAttribute* getVertexAttributes() const { return mVertexAttributes.data(); } + Buffer *getElementArrayBuffer() const { return mElementArrayBuffer.get(); } + void setElementArrayBuffer(Buffer *buffer); + GLuint getElementArrayBufferId() const { return mElementArrayBuffer.id(); } + size_t getMaxAttribs() const { return mVertexAttributes.size(); } + + private: + GLuint mId; + + rx::VertexArrayImpl *mVertexArray; + std::vector mVertexAttributes; + BindingPointer mElementArrayBuffer; +}; + +} + +#endif // LIBGLESV2_VERTEXARRAY_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp b/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp new file mode 100644 index 0000000000..7d011ef758 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp @@ -0,0 +1,56 @@ +#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. +// +// Implementation of the state class for mananging GLES 3 Vertex Array Objects. +// + +#include "libGLESv2/VertexAttribute.h" + +namespace gl +{ + +VertexAttribute::VertexAttribute() + : enabled(false), + type(GL_FLOAT), + size(4), + normalized(false), + pureInteger(false), + stride(0), + pointer(NULL), + divisor(0) +{ +} + +size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib) +{ + GLuint size = attrib.size; + switch (attrib.type) + { + case GL_BYTE: return size * sizeof(GLbyte); + case GL_UNSIGNED_BYTE: return size * sizeof(GLubyte); + case GL_SHORT: return size * sizeof(GLshort); + case GL_UNSIGNED_SHORT: return size * sizeof(GLushort); + case GL_INT: return size * sizeof(GLint); + case GL_UNSIGNED_INT: return size * sizeof(GLuint); + case GL_INT_2_10_10_10_REV: return 4; + case GL_UNSIGNED_INT_2_10_10_10_REV: return 4; + case GL_FIXED: return size * sizeof(GLfixed); + case GL_HALF_FLOAT: return size * sizeof(GLhalf); + case GL_FLOAT: return size * sizeof(GLfloat); + default: UNREACHABLE(); return size * sizeof(GLfloat); + } +} + +size_t ComputeVertexAttributeStride(const VertexAttribute& attrib) +{ + if (!attrib.enabled) + { + return 16; + } + return attrib.stride ? attrib.stride : ComputeVertexAttributeTypeSize(attrib); +} + +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.h b/src/3rdparty/angle/src/libGLESv2/VertexAttribute.h new file mode 100644 index 0000000000..e9757b618b --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/VertexAttribute.h @@ -0,0 +1,119 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// +// Helper structure describing a single vertex attribute +// + +#ifndef LIBGLESV2_VERTEXATTRIBUTE_H_ +#define LIBGLESV2_VERTEXATTRIBUTE_H_ + +#include "libGLESv2/Buffer.h" + +namespace gl +{ + +struct VertexAttribute +{ + bool enabled; // From glEnable/DisableVertexAttribArray + + GLenum type; + GLuint size; + bool normalized; + bool pureInteger; + GLuint stride; // 0 means natural stride + + union + { + const GLvoid *pointer; + GLintptr offset; + }; + BindingPointer buffer; // Captured when glVertexAttribPointer is called. + + GLuint divisor; + + VertexAttribute(); +}; + +template +T QuerySingleVertexAttributeParameter(const VertexAttribute& attrib, GLenum pname) +{ + switch (pname) + { + case GL_VERTEX_ATTRIB_ARRAY_ENABLED: + return static_cast(attrib.enabled ? GL_TRUE : GL_FALSE); + case GL_VERTEX_ATTRIB_ARRAY_SIZE: + return static_cast(attrib.size); + case GL_VERTEX_ATTRIB_ARRAY_STRIDE: + return static_cast(attrib.stride); + case GL_VERTEX_ATTRIB_ARRAY_TYPE: + return static_cast(attrib.type); + case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: + return static_cast(attrib.normalized ? GL_TRUE : GL_FALSE); + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: + return static_cast(attrib.buffer.id()); + case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: + return static_cast(attrib.divisor); + case GL_VERTEX_ATTRIB_ARRAY_INTEGER: + return static_cast(attrib.pureInteger ? GL_TRUE : GL_FALSE); + default: + UNREACHABLE(); + return static_cast(0); + } +} + +size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib); +size_t ComputeVertexAttributeStride(const VertexAttribute& attrib); + +struct VertexAttribCurrentValueData +{ + union + { + GLfloat FloatValues[4]; + GLint IntValues[4]; + GLuint UnsignedIntValues[4]; + }; + GLenum Type; + + void setFloatValues(const GLfloat floatValues[4]) + { + for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++) + { + FloatValues[valueIndex] = floatValues[valueIndex]; + } + Type = GL_FLOAT; + } + + void setIntValues(const GLint intValues[4]) + { + for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++) + { + IntValues[valueIndex] = intValues[valueIndex]; + } + Type = GL_INT; + } + + void setUnsignedIntValues(const GLuint unsignedIntValues[4]) + { + for (unsigned int valueIndex = 0; valueIndex < 4; valueIndex++) + { + UnsignedIntValues[valueIndex] = unsignedIntValues[valueIndex]; + } + Type = GL_UNSIGNED_INT; + } + + bool operator==(const VertexAttribCurrentValueData &other) + { + return (Type == other.Type && memcmp(FloatValues, other.FloatValues, sizeof(float) * 4) == 0); + } + + bool operator!=(const VertexAttribCurrentValueData &other) + { + return !(*this == other); + } +}; + +} + +#endif // LIBGLESV2_VERTEXATTRIBUTE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp new file mode 100644 index 0000000000..bc929c7d0c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp @@ -0,0 +1,196 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2 + +#include "libGLESv2/angletypes.h" +#include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/VertexAttribute.h" + +namespace gl +{ + +SamplerState::SamplerState() + : minFilter(GL_NEAREST_MIPMAP_LINEAR), + magFilter(GL_LINEAR), + wrapS(GL_REPEAT), + wrapT(GL_REPEAT), + wrapR(GL_REPEAT), + maxAnisotropy(1.0f), + baseLevel(0), + maxLevel(1000), + minLod(-FLT_MAX), + maxLod(FLT_MAX), + compareMode(GL_NONE), + compareFunc(GL_LEQUAL), + swizzleRed(GL_RED), + swizzleGreen(GL_GREEN), + swizzleBlue(GL_BLUE), + swizzleAlpha(GL_ALPHA) +{} + +bool SamplerState::swizzleRequired() const +{ + return swizzleRed != GL_RED || swizzleGreen != GL_GREEN || + swizzleBlue != GL_BLUE || swizzleAlpha != GL_ALPHA; +} + +static void MinMax(int a, int b, int *minimum, int *maximum) +{ + if (a < b) + { + *minimum = a; + *maximum = b; + } + else + { + *minimum = b; + *maximum = a; + } +} + +bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection) +{ + int minSourceX, maxSourceX, minSourceY, maxSourceY; + MinMax(source.x, source.x + source.width, &minSourceX, &maxSourceX); + MinMax(source.y, source.y + source.height, &minSourceY, &maxSourceY); + + int minClipX, maxClipX, minClipY, maxClipY; + MinMax(clip.x, clip.x + clip.width, &minClipX, &maxClipX); + MinMax(clip.y, clip.y + clip.height, &minClipY, &maxClipY); + + if (minSourceX >= maxClipX || maxSourceX <= minClipX || minSourceY >= maxClipY || maxSourceY <= minClipY) + { + if (intersection) + { + intersection->x = minSourceX; + intersection->y = maxSourceY; + intersection->width = maxSourceX - minSourceX; + intersection->height = maxSourceY - minSourceY; + } + + return false; + } + else + { + if (intersection) + { + intersection->x = std::max(minSourceX, minClipX); + intersection->y = std::max(minSourceY, minClipY); + intersection->width = std::min(maxSourceX, maxClipX) - std::max(minSourceX, minClipX); + intersection->height = std::min(maxSourceY, maxClipY) - std::max(minSourceY, minClipY); + } + + return true; + } +} + +VertexFormat::VertexFormat() + : mType(GL_NONE), + mNormalized(GL_FALSE), + mComponents(0), + mPureInteger(false) +{} + +VertexFormat::VertexFormat(GLenum type, GLboolean normalized, GLuint components, bool pureInteger) + : mType(type), + mNormalized(normalized), + mComponents(components), + mPureInteger(pureInteger) +{ + // Float data can not be normalized, so ignore the user setting + if (mType == GL_FLOAT || mType == GL_HALF_FLOAT || mType == GL_FIXED) + { + mNormalized = GL_FALSE; + } +} + +VertexFormat::VertexFormat(const VertexAttribute &attrib) + : mType(attrib.type), + mNormalized(attrib.normalized ? GL_TRUE : GL_FALSE), + mComponents(attrib.size), + mPureInteger(attrib.pureInteger) +{ + // Ensure we aren't initializing a vertex format which should be using + // the current-value type + ASSERT(attrib.enabled); + + // Float data can not be normalized, so ignore the user setting + if (mType == GL_FLOAT || mType == GL_HALF_FLOAT || mType == GL_FIXED) + { + mNormalized = GL_FALSE; + } +} + +VertexFormat::VertexFormat(const VertexAttribute &attrib, GLenum currentValueType) + : mType(attrib.type), + mNormalized(attrib.normalized ? GL_TRUE : GL_FALSE), + mComponents(attrib.size), + mPureInteger(attrib.pureInteger) +{ + if (!attrib.enabled) + { + mType = currentValueType; + mNormalized = GL_FALSE; + mComponents = 4; + mPureInteger = (currentValueType != GL_FLOAT); + } + + // Float data can not be normalized, so ignore the user setting + if (mType == GL_FLOAT || mType == GL_HALF_FLOAT || mType == GL_FIXED) + { + mNormalized = GL_FALSE; + } +} + +void VertexFormat::GetInputLayout(VertexFormat *inputLayout, + ProgramBinary *programBinary, + const VertexAttribute *attributes, + const gl::VertexAttribCurrentValueData *currentValues) +{ + for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++) + { + int semanticIndex = programBinary->getSemanticIndex(attributeIndex); + + if (semanticIndex != -1) + { + inputLayout[semanticIndex] = VertexFormat(attributes[attributeIndex], currentValues[attributeIndex].Type); + } + } +} + +bool VertexFormat::operator==(const VertexFormat &other) const +{ + return (mType == other.mType && + mComponents == other.mComponents && + mNormalized == other.mNormalized && + mPureInteger == other.mPureInteger ); +} + +bool VertexFormat::operator!=(const VertexFormat &other) const +{ + return !(*this == other); +} + +bool VertexFormat::operator<(const VertexFormat& other) const +{ + if (mType != other.mType) + { + return mType < other.mType; + } + if (mNormalized != other.mNormalized) + { + return mNormalized < other.mNormalized; + } + if (mComponents != other.mComponents) + { + return mComponents < other.mComponents; + } + return mPureInteger < other.mPureInteger; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.h b/src/3rdparty/angle/src/libGLESv2/angletypes.h index b2f0cad265..79ad810e9e 100644 --- a/src/3rdparty/angle/src/libGLESv2/angletypes.h +++ b/src/3rdparty/angle/src/libGLESv2/angletypes.h @@ -9,13 +9,22 @@ #ifndef LIBGLESV2_ANGLETYPES_H_ #define LIBGLESV2_ANGLETYPES_H_ +#include "libGLESv2/constants.h" +#include "common/RefCountObject.h" + namespace gl { +class Buffer; +class ProgramBinary; +struct VertexAttribute; +struct VertexAttribCurrentValueData; enum TextureType { TEXTURE_2D, TEXTURE_CUBE, + TEXTURE_3D, + TEXTURE_2D_ARRAY, TEXTURE_TYPE_COUNT, TEXTURE_UNKNOWN @@ -27,20 +36,56 @@ enum SamplerType SAMPLER_VERTEX }; +template struct Color { - float red; - float green; - float blue; - float alpha; + T red; + T green; + T blue; + T alpha; + + Color() : red(0), green(0), blue(0), alpha(0) { } + Color(T r, T g, T b, T a) : red(r), green(g), blue(b), alpha(a) { } }; +typedef Color ColorF; +typedef Color ColorI; +typedef Color ColorUI; + struct Rectangle { int x; int y; int width; int height; + + Rectangle() : x(0), y(0), width(0), height(0) { } + Rectangle(int x_in, int y_in, int width_in, int height_in) : x(x_in), y(y_in), width(width_in), height(height_in) { } +}; + +bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection); + +struct Box +{ + int x; + int y; + int z; + int width; + int height; + int depth; + + Box() : x(0), y(0), z(0), width(0), height(0), depth(0) { } + Box(int x_in, int y_in, int z_in, int width_in, int height_in, int depth_in) : x(x_in), y(y_in), z(z_in), width(width_in), height(height_in), depth(depth_in) { } +}; + +struct Extents +{ + int width; + int height; + int depth; + + Extents() : width(0), height(0), depth(0) { } + Extents(int width_, int height_, int depth_) : width(width_), height(height_), depth(depth_) { } }; struct RasterizerState @@ -55,6 +100,8 @@ struct RasterizerState bool pointDrawMode; bool multiSample; + + bool rasterizerDiscard; }; struct BlendState @@ -100,28 +147,125 @@ struct DepthStencilState struct SamplerState { + SamplerState(); + GLenum minFilter; GLenum magFilter; GLenum wrapS; GLenum wrapT; + GLenum wrapR; float maxAnisotropy; - int lodOffset; + + GLint baseLevel; + GLint maxLevel; + GLfloat minLod; + GLfloat maxLod; + + GLenum compareMode; + GLenum compareFunc; + + GLenum swizzleRed; + GLenum swizzleGreen; + GLenum swizzleBlue; + GLenum swizzleAlpha; + + bool swizzleRequired() const; }; struct ClearParameters { - GLbitfield mask; - - Color colorClearValue; + bool clearColor[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; + ColorF colorFClearValue; + ColorI colorIClearValue; + ColorUI colorUIClearValue; + GLenum colorClearType; bool colorMaskRed; bool colorMaskGreen; bool colorMaskBlue; bool colorMaskAlpha; + bool clearDepth; float depthClearValue; + bool clearStencil; GLint stencilClearValue; GLuint stencilWriteMask; + + bool scissorEnabled; + Rectangle scissor; +}; + +struct PixelUnpackState +{ + BindingPointer pixelBuffer; + GLint alignment; + + PixelUnpackState() + : alignment(4) + {} + + explicit PixelUnpackState(GLint alignmentIn) + : alignment(alignmentIn) + {} +}; + +struct PixelPackState +{ + BindingPointer pixelBuffer; + GLint alignment; + bool reverseRowOrder; + + PixelPackState() + : alignment(4), + reverseRowOrder(false) + {} + + explicit PixelPackState(GLint alignmentIn, bool reverseRowOrderIn) + : alignment(alignmentIn), + reverseRowOrder(reverseRowOrderIn) + {} +}; + +struct VertexFormat +{ + GLenum mType; + GLboolean mNormalized; + GLuint mComponents; + bool mPureInteger; + + VertexFormat(); + VertexFormat(GLenum type, GLboolean normalized, GLuint components, bool pureInteger); + explicit VertexFormat(const VertexAttribute &attribute); + VertexFormat(const VertexAttribute &attribute, GLenum currentValueType); + + static void GetInputLayout(VertexFormat *inputLayout, + ProgramBinary *programBinary, + const VertexAttribute *attributes, + const gl::VertexAttribCurrentValueData *currentValues); + + bool operator==(const VertexFormat &other) const; + bool operator!=(const VertexFormat &other) const; + bool operator<(const VertexFormat& other) const; +}; + +} + +namespace rx +{ + +enum VertexConversionType +{ + VERTEX_CONVERT_NONE = 0, + VERTEX_CONVERT_CPU = 1, + VERTEX_CONVERT_GPU = 2, + VERTEX_CONVERT_BOTH = 3 +}; + +enum D3DWorkaroundType +{ + ANGLE_D3D_WORKAROUND_NONE, + ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION, + ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION }; } diff --git a/src/3rdparty/angle/src/libGLESv2/constants.h b/src/3rdparty/angle/src/libGLESv2/constants.h index 9f24d66a7d..c87f92d497 100644 --- a/src/3rdparty/angle/src/libGLESv2/constants.h +++ b/src/3rdparty/angle/src/libGLESv2/constants.h @@ -22,12 +22,26 @@ enum 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_DRAW_BUFFERS = 8, + IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS = IMPLEMENTATION_MAX_DRAW_BUFFERS + 2, // 2 extra for depth and/or stencil buffers + + IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS = 16, + IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS = 16, + IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS = IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS + + IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS, + + IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS = 4, -const float ALIASED_LINE_WIDTH_RANGE_MIN = 1.0f; -const float ALIASED_LINE_WIDTH_RANGE_MAX = 1.0f; -const float ALIASED_POINT_SIZE_RANGE_MIN = 1.0f; + // These are the maximums the implementation can support + // The actual GL caps are limited by the device caps + // and should be queried from the Context + IMPLEMENTATION_MAX_2D_TEXTURE_SIZE = 16384, + IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE = 16384, + IMPLEMENTATION_MAX_3D_TEXTURE_SIZE = 2048, + IMPLEMENTATION_MAX_2D_ARRAY_TEXTURE_LAYERS = 2048, + + IMPLEMENTATION_MAX_TEXTURE_LEVELS = 15 // 1+log2 of MAX_TEXTURE_SIZE +}; } diff --git a/src/3rdparty/angle/src/libGLESv2/formatutils.cpp b/src/3rdparty/angle/src/libGLESv2/formatutils.cpp new file mode 100644 index 0000000000..8cc2e19a83 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/formatutils.cpp @@ -0,0 +1,1548 @@ +#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 +// found in the LICENSE file. +// + +// formatutils.cpp: Queries for GL image formats. + +#include "common/mathutil.h" +#include "libGLESv2/formatutils.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/imageformats.h" +#include "libGLESv2/renderer/copyimage.h" + +namespace gl +{ + +// ES2 requires that format is equal to internal format at all glTex*Image2D entry points and the implementation +// can decide the true, sized, internal format. The ES2FormatMap determines the internal format for all valid +// format and type combinations. + +struct FormatTypeInfo +{ + 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; + +// 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))); +} + +FormatMap BuildFormatMap() +{ + FormatMap map; + + using namespace rx; + + // | Format | Type | Internal format | Color write function | + InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8, WriteColor ); + InsertFormatMapping(&map, GL_RGBA, GL_BYTE, GL_RGBA8_SNORM, WriteColor ); + InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA4, WriteColor ); + InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_RGB5_A1, WriteColor ); + InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2, WriteColor ); + InsertFormatMapping(&map, GL_RGBA, GL_FLOAT, GL_RGBA32F, WriteColor); + InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT, GL_RGBA16F, WriteColor); + InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA16F, WriteColor); + + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_RGBA8UI, WriteColor ); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_BYTE, GL_RGBA8I, WriteColor ); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_RGBA16UI, WriteColor ); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_SHORT, GL_RGBA16I, WriteColor ); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_RGBA32UI, WriteColor ); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_INT, GL_RGBA32I, WriteColor ); + InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2UI, WriteColor ); + + InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8, WriteColor ); + InsertFormatMapping(&map, GL_RGB, GL_BYTE, GL_RGB8_SNORM, WriteColor ); + InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB565, WriteColor ); + InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_R11F_G11F_B10F, WriteColor ); + InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_RGB9_E5, WriteColor ); + InsertFormatMapping(&map, GL_RGB, GL_FLOAT, GL_RGB32F, WriteColor ); + InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT, GL_RGB16F, WriteColor ); + InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, GL_RGB16F, WriteColor ); + + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_RGB8UI, WriteColor ); + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_BYTE, GL_RGB8I, WriteColor ); + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_RGB16UI, WriteColor ); + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_SHORT, GL_RGB16I, WriteColor ); + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_RGB32UI, WriteColor ); + InsertFormatMapping(&map, GL_RGB_INTEGER, GL_INT, GL_RGB32I, WriteColor ); + + InsertFormatMapping(&map, GL_RG, GL_UNSIGNED_BYTE, GL_RG8, WriteColor ); + InsertFormatMapping(&map, GL_RG, GL_BYTE, GL_RG8_SNORM, WriteColor ); + InsertFormatMapping(&map, GL_RG, GL_FLOAT, GL_RG32F, WriteColor ); + InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT, GL_RG16F, WriteColor ); + InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT_OES, GL_RG16F, WriteColor ); + + InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_RG8UI, WriteColor ); + InsertFormatMapping(&map, GL_RG_INTEGER, GL_BYTE, GL_RG8I, WriteColor ); + InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_RG16UI, WriteColor ); + InsertFormatMapping(&map, GL_RG_INTEGER, GL_SHORT, GL_RG16I, WriteColor ); + InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_RG32UI, WriteColor ); + InsertFormatMapping(&map, GL_RG_INTEGER, GL_INT, GL_RG32I, WriteColor ); + + InsertFormatMapping(&map, GL_RED, GL_UNSIGNED_BYTE, GL_R8, WriteColor ); + InsertFormatMapping(&map, GL_RED, GL_BYTE, GL_R8_SNORM, WriteColor ); + InsertFormatMapping(&map, GL_RED, GL_FLOAT, GL_R32F, WriteColor ); + InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT, GL_R16F, WriteColor ); + InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT_OES, GL_R16F, WriteColor ); + + InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_R8UI, WriteColor ); + InsertFormatMapping(&map, GL_RED_INTEGER, GL_BYTE, GL_R8I, WriteColor ); + InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_R16UI, WriteColor ); + InsertFormatMapping(&map, GL_RED_INTEGER, GL_SHORT, GL_R16I, WriteColor ); + InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_R32UI, WriteColor ); + InsertFormatMapping(&map, GL_RED_INTEGER, GL_INT, GL_R32I, WriteColor ); + + InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE8_ALPHA8_EXT, WriteColor ); + InsertFormatMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE8_EXT, WriteColor ); + InsertFormatMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA8_EXT, WriteColor ); + InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA32F_EXT, WriteColor ); + InsertFormatMapping(&map, GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE32F_EXT, WriteColor ); + InsertFormatMapping(&map, GL_ALPHA, GL_FLOAT, GL_ALPHA32F_EXT, WriteColor ); + InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_LUMINANCE_ALPHA16F_EXT, WriteColor ); + InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA16F_EXT, WriteColor ); + InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, GL_LUMINANCE16F_EXT, WriteColor ); + InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE16F_EXT, WriteColor ); + InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT, GL_ALPHA16F_EXT, WriteColor ); + InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA16F_EXT, WriteColor ); + + InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA8_EXT, WriteColor ); + InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_BGRA4_ANGLEX, WriteColor ); + InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_BGR5_A1_ANGLEX, WriteColor ); + + InsertFormatMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB8, WriteColor ); + InsertFormatMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB8_ALPHA8, WriteColor ); + + InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, NULL ); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL ); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL ); + InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL ); + + InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT16, NULL ); + InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT32_OES, NULL ); + InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT32F, NULL ); + + InsertFormatMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, GL_STENCIL_INDEX8, NULL ); + + InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8, NULL ); + InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_DEPTH32F_STENCIL8, NULL ); + + return map; +} + +static const FormatMap &GetFormatMap() +{ + 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; + +ES3FormatSet BuildES3FormatSet() +{ + 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 )); + + // 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; +} + +static const ES3FormatSet &GetES3FormatSet() +{ + static const ES3FormatSet es3FormatSet = BuildES3FormatSet(); + return es3FormatSet; +} + +// 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 ))); + + 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; +} + +static bool UnimplementedSupport(GLuint, const Extensions &) +{ + return false; +} + +static bool NeverSupported(GLuint, const Extensions &) +{ + return false; +} + +template +static bool RequireESVersion(GLuint clientVersion, const Extensions &) +{ + return clientVersion >= minCoreGLVersion; +} + +// Pointer to a boolean memeber of the Extensions struct +typedef bool(Extensions::*ExtensionBool); + +// Check support for a single extension +template +static bool RequireExtension(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) +{ + return clientVersion >= minCoreGLVersion || extensions.*bool1; +} + +// Check for a minimum client version or two extensions +template +static bool RequireESVersionOrExtensions(GLuint clientVersion, const Extensions &extensions) +{ + return clientVersion >= minCoreGLVersion || (extensions.*bool1 || extensions.*bool2); +} + +// Check support for two extensions +template +static bool RequireExtensions(GLuint, const Extensions &extensions) +{ + return 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; + +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))); + + // 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> ))); + + // 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 ))); + + // 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))); + + // 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))); + + // 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))); + + // 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 ))); + + // 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 ))); + + // 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 ))); + + return map; +} + +static const InternalFormatInfoMap &GetInternalFormatMap() +{ + static const InternalFormatInfoMap formatMap = BuildInternalFormatInfoMap(); + 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; + + const InternalFormatInfoMap &formats = GetInternalFormatMap(); + for (InternalFormatInfoMap::const_iterator i = formats.begin(); i != formats.end(); i++) + { + if (i->second.mPixelBits > 0) + { + result.insert(i->first); + } + } + + 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 InternalFormatInfoMap &internalFormats = GetInternalFormatMap(); + for (InternalFormatInfoMap::const_iterator i = internalFormats.begin(); i != internalFormats.end(); i++) + { + 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; + } + } + 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; + } +} + +bool IsValidCopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle, GLuint clientVersion) +{ + 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) + { + return true; + } + else + { + return false; + } +} + +GLenum GetFormat(GLenum internalFormat) +{ + InternalFormatInfo internalFormatInfo; + if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) + { + return internalFormatInfo.mFormat; + } + else + { + UNREACHABLE(); + return GL_NONE; + } +} + +GLenum GetType(GLenum internalFormat) +{ + InternalFormatInfo internalFormatInfo; + if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) + { + return internalFormatInfo.mType; + } + else + { + UNREACHABLE(); + return GL_NONE; + } +} + +GLenum GetComponentType(GLenum internalFormat) +{ + InternalFormatInfo internalFormatInfo; + if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) + { + return internalFormatInfo.mComponentType; + } + else + { + UNREACHABLE(); + return GL_NONE; + } +} + +GLuint GetComponentCount(GLenum internalFormat) +{ + InternalFormatInfo internalFormatInfo; + if (GetInternalFormatInfo(internalFormat, &internalFormatInfo)) + { + return internalFormatInfo.mComponentCount; + } + 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) + { + GLsizei numBlocksWide = (width + internalFormatInfo.mCompressedBlockWidth - 1) / internalFormatInfo.mCompressedBlockWidth; + GLsizei numBlocksHight = (height + internalFormatInfo.mCompressedBlockHeight - 1) / internalFormatInfo.mCompressedBlockHeight; + + return (internalFormatInfo.mPixelBits * numBlocksWide * numBlocksHight) / 8; + } + 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; + } + } + } + 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) +{ + 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 FormatSet &GetAllSizedInternalFormats() +{ + static FormatSet formatSet = BuildAllSizedInternalFormatSet(); + 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 new file mode 100644 index 0000000000..2f592798b8 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/formatutils.h @@ -0,0 +1,88 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// formatutils.h: Queries for GL image formats. + +#ifndef LIBGLESV2_FORMATUTILS_H_ +#define LIBGLESV2_FORMATUTILS_H_ + +#include "angle_gl.h" + +#include "libGLESv2/Caps.h" +#include "libGLESv2/angletypes.h" + +#include + +typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); + +typedef void (*LoadImageFunction)(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +typedef void (*InitializeTextureDataFunction)(size_t width, size_t height, size_t depth, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +typedef void (*ColorReadFunction)(const void *source, void *dest); +typedef void (*ColorWriteFunction)(const void *source, void *dest); +typedef void (*ColorCopyFunction)(const void *source, void *dest); + +typedef void (*VertexCopyFunction)(const void *input, size_t stride, size_t count, void *output); + +namespace gl +{ + +typedef std::set FormatSet; + +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); + +bool IsValidFormatCombination(GLenum internalFormat, GLenum format, GLenum type, const Extensions &extensions, GLuint clientVersion); +bool IsValidCopyTexImageCombination(GLenum textureInternalFormat, GLenum frameBufferInternalFormat, GLuint readBufferHandle, GLuint clientVersion); + +bool IsRenderingSupported(GLenum internalFormat, const Extensions &extensions, GLuint clientVersion); +bool IsFilteringSupported(GLenum internalFormat, const Extensions &extensions, GLuint clientVersion); + +bool IsSizedInternalFormat(GLenum internalFormat); +GLenum GetSizedInternalFormat(GLenum format, GLenum type); + +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 GetTypeBytes(GLenum type); +bool IsSpecialInterpretationType(GLenum type); +bool IsFloatOrFixedComponentType(GLenum type); + +GLenum GetFormat(GLenum internalFormat); +GLenum GetType(GLenum internalFormat); + +GLenum GetComponentType(GLenum internalFormat); +GLuint GetComponentCount(GLenum internalFormat); +GLenum GetColorEncoding(GLenum internalFormat); + +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); + +bool IsFormatCompressed(GLenum internalFormat); +GLuint GetCompressedBlockWidth(GLenum internalFormat); +GLuint GetCompressedBlockHeight(GLenum internalFormat); + +const FormatSet &GetAllSizedInternalFormats(); + +ColorWriteFunction GetColorWriteFunction(GLenum format, GLenum type); + +} + +#endif // LIBGLESV2_FORMATUTILS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp index 814dfbf965..5e2ec4a4ee 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp @@ -1,6 +1,6 @@ #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,7 +10,8 @@ #include "common/version.h" #include "libGLESv2/main.h" -#include "libGLESv2/utilities.h" +#include "common/utilities.h" +#include "libGLESv2/formatutils.h" #include "libGLESv2/Buffer.h" #include "libGLESv2/Fence.h" #include "libGLESv2/Framebuffer.h" @@ -20,804 +21,552 @@ #include "libGLESv2/Texture.h" #include "libGLESv2/Query.h" #include "libGLESv2/Context.h" +#include "libGLESv2/VertexArray.h" +#include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/TransformFeedback.h" +#include "libGLESv2/FramebufferAttachment.h" -bool validImageSize(GLint level, GLsizei width, GLsizei height) +#include "libGLESv2/validationES.h" +#include "libGLESv2/validationES2.h" +#include "libGLESv2/validationES3.h" +#include "libGLESv2/queryconversions.h" + +extern "C" { - if (level < 0 || width < 0 || height < 0) - { - return false; - } - if (gl::getContext() && gl::getContext()->supportsNonPower2Texture()) - { - return true; - } +// OpenGL ES 2.0 functions - if (level == 0) - { - return true; - } +void __stdcall glActiveTexture(GLenum texture) +{ + EVENT("(GLenum texture = 0x%X)", texture); + + gl::Context *context = gl::getNonLostContext(); - if (gl::isPow2(width) && gl::isPow2(height)) + if (context) { - return true; - } + if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getMaximumCombinedTextureImageUnits() - 1) + { + return gl::error(GL_INVALID_ENUM); + } - return false; + context->getState().setActiveSampler(texture - GL_TEXTURE0); + } } -// Verify that format/type are one of the combinations from table 3.4. -bool checkTextureFormatType(GLenum format, GLenum type) +void __stdcall glAttachShader(GLuint program, GLuint shader) { - // validate by itself (used as secondary key below) - switch (format) - { - case GL_RGBA: - case GL_BGRA_EXT: - case GL_RGB: - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - case GL_DEPTH_COMPONENT: - case GL_DEPTH_STENCIL_OES: - break; - default: - return gl::error(GL_INVALID_ENUM, false); - } + EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); - // invalid -> sets INVALID_ENUM - // invalid + combination -> sets INVALID_OPERATION - switch (type) - { - case GL_UNSIGNED_BYTE: - switch (format) - { - case GL_RGBA: - case GL_BGRA_EXT: - case GL_RGB: - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - return true; - default: - return gl::error(GL_INVALID_OPERATION, false); - } + gl::Context *context = gl::getNonLostContext(); - case GL_FLOAT: - case GL_HALF_FLOAT_OES: - switch (format) - { - case GL_RGBA: - case GL_RGB: - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - return true; - default: - return gl::error(GL_INVALID_OPERATION, false); - } + if (context) + { + gl::Program *programObject = context->getProgram(program); + gl::Shader *shaderObject = context->getShader(shader); - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - switch (format) + if (!programObject) { - case GL_RGBA: - return true; - default: - return gl::error(GL_INVALID_OPERATION, false); + if (context->getShader(program)) + { + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); + } } - case GL_UNSIGNED_SHORT_5_6_5: - switch (format) + if (!shaderObject) { - case GL_RGB: - return true; - default: - return gl::error(GL_INVALID_OPERATION, false); + if (context->getProgram(shader)) + { + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); + } } - case GL_UNSIGNED_SHORT: - case GL_UNSIGNED_INT: - switch (format) + if (!programObject->attachShader(shaderObject)) { - case GL_DEPTH_COMPONENT: - return true; - default: - return gl::error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION); } + } +} + +void __stdcall glBeginQueryEXT(GLenum target, GLuint id) +{ + EVENT("(GLenum target = 0x%X, GLuint %d)", target, id); + + gl::Context *context = gl::getNonLostContext(); - case GL_UNSIGNED_INT_24_8_OES: - switch (format) + if (context) + { + if (!ValidateBeginQuery(context, target, id)) { - case GL_DEPTH_STENCIL_OES: - return true; - default: - return gl::error(GL_INVALID_OPERATION, false); + return; } - default: - return gl::error(GL_INVALID_ENUM, false); + context->beginQuery(target, id); } } -bool validateSubImageParams2D(bool compressed, GLsizei width, GLsizei height, - GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type, - gl::Texture2D *texture) +void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* name) { - if (!texture) - { - return gl::error(GL_INVALID_OPERATION, false); - } + EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name); - if (compressed != texture->isCompressed(level)) + if (index >= gl::MAX_VERTEX_ATTRIBS) { - return gl::error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_VALUE); } - if (format != GL_NONE) + gl::Context *context = gl::getNonLostContext(); + + if (context) { - GLenum internalformat = gl::ConvertSizedInternalFormat(format, type); - if (internalformat != texture->getInternalFormat(level)) + gl::Program *programObject = context->getProgram(program); + + if (!programObject) { - return gl::error(GL_INVALID_OPERATION, false); + if (context->getShader(program)) + { + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); + } } - } - if (compressed) - { - if ((width % 4 != 0 && width != texture->getWidth(0)) || - (height % 4 != 0 && height != texture->getHeight(0))) + if (strncmp(name, "gl_", 3) == 0) { - return gl::error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_OPERATION); } - } - if (xoffset + width > texture->getWidth(level) || - yoffset + height > texture->getHeight(level)) - { - return gl::error(GL_INVALID_VALUE, false); + programObject->bindAttributeLocation(index, name); } - - return true; } -bool validateSubImageParamsCube(bool compressed, GLsizei width, GLsizei height, - GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type, - gl::TextureCubeMap *texture) +void __stdcall glBindBuffer(GLenum target, GLuint buffer) { - if (!texture) - { - return gl::error(GL_INVALID_OPERATION, false); - } + EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer); - if (compressed != texture->isCompressed(target, level)) - { - return gl::error(GL_INVALID_OPERATION, false); - } + gl::Context *context = gl::getNonLostContext(); - if (format != GL_NONE) + if (context) { - GLenum internalformat = gl::ConvertSizedInternalFormat(format, type); - if (internalformat != texture->getInternalFormat(target, level)) + if (!gl::ValidBufferTarget(context, target)) { - return gl::error(GL_INVALID_OPERATION, false); + return gl::error(GL_INVALID_ENUM); } - } - if (compressed) - { - if ((width % 4 != 0 && width != texture->getWidth(target, 0)) || - (height % 4 != 0 && height != texture->getHeight(target, 0))) + switch (target) { - return gl::error(GL_INVALID_OPERATION, false); + case GL_ARRAY_BUFFER: + context->bindArrayBuffer(buffer); + return; + case GL_ELEMENT_ARRAY_BUFFER: + context->bindElementArrayBuffer(buffer); + return; + case GL_COPY_READ_BUFFER: + context->bindCopyReadBuffer(buffer); + return; + case GL_COPY_WRITE_BUFFER: + context->bindCopyWriteBuffer(buffer); + return; + case GL_PIXEL_PACK_BUFFER: + context->bindPixelPackBuffer(buffer); + return; + case GL_PIXEL_UNPACK_BUFFER: + context->bindPixelUnpackBuffer(buffer); + return; + case GL_UNIFORM_BUFFER: + context->bindGenericUniformBuffer(buffer); + return; + case GL_TRANSFORM_FEEDBACK_BUFFER: + context->bindGenericTransformFeedbackBuffer(buffer); + return; + default: + return gl::error(GL_INVALID_ENUM); } } +} + +void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer) +{ + EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer); - if (xoffset + width > texture->getWidth(target, level) || - yoffset + height > texture->getHeight(target, level)) + if (!gl::ValidFramebufferTarget(target)) { - return gl::error(GL_INVALID_VALUE, false); + return gl::error(GL_INVALID_ENUM); } - return true; -} + gl::Context *context = gl::getNonLostContext(); -// check for combinations of format and type that are valid for ReadPixels -bool validReadFormatType(GLenum format, GLenum type) -{ - switch (format) + if (context) { - case GL_RGBA: - switch (type) + if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) { - case GL_UNSIGNED_BYTE: - break; - default: - return false; + context->bindReadFramebuffer(framebuffer); } - break; - case GL_BGRA_EXT: - switch (type) + + if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: - case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: - break; - default: - return false; + context->bindDrawFramebuffer(framebuffer); } - break; - default: - return false; } - return true; } -extern "C" -{ - -void __stdcall glActiveTexture(GLenum texture) +void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer) { - EVENT("(GLenum texture = 0x%X)", texture); + EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer); - try + if (target != GL_RENDERBUFFER) { - gl::Context *context = gl::getNonLostContext(); + return gl::error(GL_INVALID_ENUM); + } - if (context) - { - if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getMaximumCombinedTextureImageUnits() - 1) - { - return gl::error(GL_INVALID_ENUM); - } + gl::Context *context = gl::getNonLostContext(); - context->setActiveSampler(texture - GL_TEXTURE0); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->bindRenderbuffer(renderbuffer); } } -void __stdcall glAttachShader(GLuint program, GLuint shader) +void __stdcall glBindTexture(GLenum target, GLuint texture) { - EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); + EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Texture *textureObject = context->getTexture(texture); - if (context) + if (textureObject && textureObject->getTarget() != target && texture != 0) { - gl::Program *programObject = context->getProgram(program); - gl::Shader *shaderObject = context->getShader(shader); - - if (!programObject) - { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } - } + return gl::error(GL_INVALID_OPERATION); + } - if (!shaderObject) + switch (target) + { + case GL_TEXTURE_2D: + context->bindTexture2D(texture); + return; + case GL_TEXTURE_CUBE_MAP: + context->bindTextureCubeMap(texture); + return; + case GL_TEXTURE_3D: + if (context->getClientVersion() < 3) { - if (context->getProgram(shader)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_ENUM); } - - if (!programObject->attachShader(shaderObject)) + context->bindTexture3D(texture); + return; + case GL_TEXTURE_2D_ARRAY: + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_ENUM); } + context->bindTexture2DArray(texture); + return; + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } -void __stdcall glBeginQueryEXT(GLenum target, GLuint id) +void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) { - EVENT("(GLenum target = 0x%X, GLuint %d)", target, id); - - try - { - switch (target) - { - case GL_ANY_SAMPLES_PASSED_EXT: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - if (id == 0) - { - return gl::error(GL_INVALID_OPERATION); - } + EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", + red, green, blue, alpha); - gl::Context *context = gl::getNonLostContext(); + gl::Context* context = gl::getNonLostContext(); - if (context) - { - context->beginQuery(target, id); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha)); } } -void __stdcall glBindAttribLocation(GLuint program, GLuint index, const GLchar* name) +void __stdcall glBlendEquation(GLenum mode) { - EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name); - - try - { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - gl::Program *programObject = context->getProgram(program); + glBlendEquationSeparate(mode, mode); +} - if (!programObject) - { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } - } +void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) +{ + EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha); - if (strncmp(name, "gl_", 3) == 0) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::Context *context = gl::getNonLostContext(); - programObject->bindAttributeLocation(index, name); - } - } - catch(std::bad_alloc&) + switch (modeRGB) { - return gl::error(GL_OUT_OF_MEMORY); - } -} + case GL_FUNC_ADD: + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + case GL_MIN: + case GL_MAX: + break; -void __stdcall glBindBuffer(GLenum target, GLuint buffer) -{ - EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer); + default: + return gl::error(GL_INVALID_ENUM); + } - try + switch (modeAlpha) { - gl::Context *context = gl::getNonLostContext(); + case GL_FUNC_ADD: + case GL_FUNC_SUBTRACT: + case GL_FUNC_REVERSE_SUBTRACT: + case GL_MIN: + case GL_MAX: + break; - if (context) - { - switch (target) - { - case GL_ARRAY_BUFFER: - context->bindArrayBuffer(buffer); - return; - case GL_ELEMENT_ARRAY_BUFFER: - context->bindElementArrayBuffer(buffer); - return; - default: - return gl::error(GL_INVALID_ENUM); - } - } + default: + return gl::error(GL_INVALID_ENUM); } - catch(std::bad_alloc&) + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setBlendEquation(modeRGB, modeAlpha); } } -void __stdcall glBindFramebuffer(GLenum target, GLuint framebuffer) +void __stdcall glBlendFunc(GLenum sfactor, GLenum dfactor) { - EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer); - - try - { - if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) - { - return gl::error(GL_INVALID_ENUM); - } + glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor); +} - gl::Context *context = gl::getNonLostContext(); +void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) +{ + EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)", + srcRGB, dstRGB, srcAlpha, dstAlpha); - if (context) - { - if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) - { - context->bindReadFramebuffer(framebuffer); - } - - if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER) - { - context->bindDrawFramebuffer(framebuffer); - } - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + 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); } -} -void __stdcall glBindRenderbuffer(GLenum target, GLuint renderbuffer) -{ - EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer); + 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; - try - { - if (target != GL_RENDERBUFFER) + case GL_SRC_ALPHA_SATURATE: + if (!context || context->getClientVersion() < 3) { return gl::error(GL_INVALID_ENUM); } + break; - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->bindRenderbuffer(renderbuffer); - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + default: + return gl::error(GL_INVALID_ENUM); } -} -void __stdcall glBindTexture(GLenum target, GLuint texture) -{ - EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture); + 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); + } - try - { - gl::Context *context = gl::getNonLostContext(); + 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; - if (context) + case GL_SRC_ALPHA_SATURATE: + if (!context || context->getClientVersion() < 3) { - gl::Texture *textureObject = context->getTexture(texture); - - if (textureObject && textureObject->getTarget() != target && texture != 0) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (target) - { - case GL_TEXTURE_2D: - context->bindTexture2D(texture); - return; - case GL_TEXTURE_CUBE_MAP: - context->bindTextureCubeMap(texture); - return; - default: - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_ENUM); } + break; + + default: + return gl::error(GL_INVALID_ENUM); } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } -} -void __stdcall glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha) -{ - EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", - red, green, blue, alpha); + bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR || + dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR); - try - { - gl::Context* context = gl::getNonLostContext(); + bool constantAlphaUsed = (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA || + dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA); - if (context) - { - context->setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha)); - } - } - catch(std::bad_alloc&) + if (constantColorUsed && constantAlphaUsed) { - return gl::error(GL_OUT_OF_MEMORY); + 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); } -} -void __stdcall glBlendEquation(GLenum mode) -{ - glBlendEquationSeparate(mode, mode); + if (context) + { + context->getState().setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha); + } } -void __stdcall glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha) +void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) { - EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha); - - try - { - switch (modeRGB) - { - case GL_FUNC_ADD: - case GL_FUNC_SUBTRACT: - case GL_FUNC_REVERSE_SUBTRACT: - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - switch (modeAlpha) - { - case GL_FUNC_ADD: - case GL_FUNC_SUBTRACT: - case GL_FUNC_REVERSE_SUBTRACT: - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - gl::Context *context = gl::getNonLostContext(); + EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)", + target, size, data, usage); - if (context) - { - context->setBlendEquation(modeRGB, modeAlpha); - } - } - catch(std::bad_alloc&) + if (size < 0) { - return gl::error(GL_OUT_OF_MEMORY); + return gl::error(GL_INVALID_VALUE); } -} - -void __stdcall glBlendFunc(GLenum sfactor, GLenum dfactor) -{ - glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor); -} -void __stdcall glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha) -{ - EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)", - srcRGB, dstRGB, srcAlpha, dstAlpha); + gl::Context *context = gl::getNonLostContext(); - try - { - 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 (usage) + { + case GL_STREAM_DRAW: + case GL_STATIC_DRAW: + case GL_DYNAMIC_DRAW: + break; - switch (dstRGB) + 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) { - 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; - default: - return gl::error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM); } + break; - 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); - } + default: + return gl::error(GL_INVALID_ENUM); + } - switch (dstAlpha) + if (context) + { + if (!gl::ValidBufferTarget(context, target)) { - 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; - default: return gl::error(GL_INVALID_ENUM); } - bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR || - dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR); + gl::Buffer *buffer = context->getState().getTargetBuffer(target); - 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) + if (!buffer) { - 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); } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha); - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + buffer->bufferData(data, size, usage); } } -void __stdcall glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage) +void __stdcall glBufferSubData(GLenum target, GLintptr offset, 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); + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)", + target, offset, size, data); - try + if (size < 0 || offset < 0) { - if (size < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } + + if (data == NULL) + { + return; + } + + gl::Context *context = gl::getNonLostContext(); - switch (usage) + if (context) + { + if (!gl::ValidBufferTarget(context, target)) { - case GL_STREAM_DRAW: - case GL_STATIC_DRAW: - case GL_DYNAMIC_DRAW: - break; - default: return gl::error(GL_INVALID_ENUM); } - gl::Context *context = gl::getNonLostContext(); + gl::Buffer *buffer = context->getState().getTargetBuffer(target); - if (context) + if (!buffer) { - gl::Buffer *buffer; - - switch (target) - { - case GL_ARRAY_BUFFER: - buffer = context->getArrayBuffer(); - break; - case GL_ELEMENT_ARRAY_BUFFER: - buffer = context->getElementArrayBuffer(); - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - if (!buffer) - { - return gl::error(GL_INVALID_OPERATION); - } - - buffer->bufferData(data, size, usage); + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } -} - -void __stdcall glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data) -{ - EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)", - target, offset, size, data); - try - { - if (size < 0 || offset < 0) + if (buffer->isMapped()) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (data == NULL) + // Check for possible overflow of size + offset + if (!rx::IsUnsignedAdditionSafe(size, offset)) { - return; + return gl::error(GL_OUT_OF_MEMORY); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (size + offset > buffer->getSize()) { - gl::Buffer *buffer; - - switch (target) - { - case GL_ARRAY_BUFFER: - buffer = context->getArrayBuffer(); - break; - case GL_ELEMENT_ARRAY_BUFFER: - buffer = context->getElementArrayBuffer(); - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - if (!buffer) - { - return gl::error(GL_INVALID_OPERATION); - } - - if ((size_t)size + offset > buffer->size()) - { - return gl::error(GL_INVALID_VALUE); - } - - buffer->bufferSubData(data, size, offset); + return gl::error(GL_INVALID_VALUE); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + buffer->bufferSubData(data, size, offset); } } @@ -825,33 +574,18 @@ GLenum __stdcall glCheckFramebufferStatus(GLenum target) { EVENT("(GLenum target = 0x%X)", target); - try + if (!gl::ValidFramebufferTarget(target)) { - if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) - { - return gl::error(GL_INVALID_ENUM, 0); - } - - gl::Context *context = gl::getNonLostContext(); + return gl::error(GL_INVALID_ENUM, 0); + } - if (context) - { - gl::Framebuffer *framebuffer = NULL; - if (target == GL_READ_FRAMEBUFFER_ANGLE) - { - framebuffer = context->getReadFramebuffer(); - } - else - { - framebuffer = context->getDrawFramebuffer(); - } + gl::Context *context = gl::getNonLostContext(); - return framebuffer->completeness(); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY, 0); + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + return framebuffer->completeness(); } return 0; @@ -859,20 +593,25 @@ GLenum __stdcall glCheckFramebufferStatus(GLenum target) void __stdcall glClear(GLbitfield mask) { - EVENT("(GLbitfield mask = %X)", mask); + EVENT("(GLbitfield mask = 0x%X)", mask); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Framebuffer *framebufferObject = context->getState().getDrawFramebuffer(); - if (context) + if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) { - context->clear(mask); + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0) + { + return gl::error(GL_INVALID_VALUE); + } + + context->clear(mask); } } @@ -881,18 +620,11 @@ void __stdcall glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclamp EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)", red, green, blue, alpha); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setClearColor(red, green, blue, alpha); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setClearColor(red, green, blue, alpha); } } @@ -900,18 +632,11 @@ void __stdcall glClearDepthf(GLclampf depth) { EVENT("(GLclampf depth = %f)", depth); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setClearDepth(depth); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setClearDepth(depth); } } @@ -919,38 +644,24 @@ void __stdcall glClearStencil(GLint s) { EVENT("(GLint s = %d)", s); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setClearStencil(s); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setClearStencil(s); } } void __stdcall glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha) { - EVENT("(GLboolean red = %d, GLboolean green = %d, GLboolean blue = %d, GLboolean alpha = %d)", + EVENT("(GLboolean red = %d, GLboolean green = %u, GLboolean blue = %u, GLboolean alpha = %u)", red, green, blue, alpha); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE); } } @@ -958,191 +669,82 @@ void __stdcall glCompileShader(GLuint shader) { EVENT("(GLuint shader = %d)", shader); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Shader *shaderObject = context->getShader(shader); - if (context) + if (!shaderObject) { - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) + if (context->getProgram(shader)) { - if (context->getProgram(shader)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); } - - shaderObject->compile(); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + shaderObject->compile(); } } -void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, +void __stdcall glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " + EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", target, level, internalformat, width, height, border, imageSize, data); - try - { - if (!validImageSize(level, width, height) || border != 0 || imageSize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - switch (internalformat) - { - 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: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + gl::Context *context = gl::getNonLostContext(); - if (border != 0) + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, internalformat, true, false, + 0, 0, width, height, border, GL_NONE, GL_NONE, data)) { - return gl::error(GL_INVALID_OPERATION); + return; } - if (width != 1 && width != 2 && width % 4 != 0) + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, internalformat, true, false, + 0, 0, 0, width, height, 1, border, GL_NONE, GL_NONE, data)) { - return gl::error(GL_INVALID_OPERATION); + return; } - if (height != 1 && height != 2 && height % 4 != 0) + if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(internalformat, GL_UNSIGNED_BYTE, width, height)) { - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + switch (target) { - if (level > context->getMaximumTextureLevel()) - { - return gl::error(GL_INVALID_VALUE); - } - - switch (target) - { - case GL_TEXTURE_2D: - if (width > (context->getMaximumTextureDimension() >> level) || - height > (context->getMaximumTextureDimension() >> level)) - { - return gl::error(GL_INVALID_VALUE); - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (width != height) - { - return gl::error(GL_INVALID_VALUE); - } - - if (width > (context->getMaximumCubeTextureDimension() >> level) || - height > (context->getMaximumCubeTextureDimension() >> level)) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - switch (internalformat) { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (!context->supportsDXT1Textures()) - { - return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (!context->supportsDXT3Textures()) - { - return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (!context->supportsDXT5Textures()) - { - return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed - } - break; - default: UNREACHABLE(); - } - - if (imageSize != gl::ComputeCompressedSize(width, height, internalformat)) - { - return gl::error(GL_INVALID_VALUE); - } - - if (target == GL_TEXTURE_2D) + case GL_TEXTURE_2D: { gl::Texture2D *texture = context->getTexture2D(); - - if (!texture) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (texture->isImmutable()) - { - return gl::error(GL_INVALID_OPERATION); - } - texture->setCompressedImage(level, internalformat, width, height, imageSize, data); } - else + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { gl::TextureCubeMap *texture = context->getTextureCubeMap(); - - if (!texture) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (texture->isImmutable()) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (target) - { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data); - break; - default: UNREACHABLE(); - } + texture->setCompressedImage(target, level, internalformat, width, height, imageSize, data); } - } + break; - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + default: + return gl::error(GL_INVALID_ENUM); + } } } @@ -1154,103 +756,54 @@ void __stdcall glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffs "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", target, level, xoffset, yoffset, width, height, format, imageSize, data); - try - { - if (!gl::IsInternalTextureTarget(target)) - { - return gl::error(GL_INVALID_ENUM); - } + gl::Context *context = gl::getNonLostContext(); - if (xoffset < 0 || yoffset < 0 || !validImageSize(level, width, height) || imageSize < 0) + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true, + xoffset, yoffset, width, height, 0, GL_NONE, GL_NONE, data)) { - return gl::error(GL_INVALID_VALUE); + return; } - switch (format) + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true, + xoffset, yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, data)) { - 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: - break; - default: - return gl::error(GL_INVALID_ENUM); + return; } - if (width == 0 || height == 0 || data == NULL) + if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(format, GL_UNSIGNED_BYTE, width, height)) { - return; + return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + switch (target) { - if (level > context->getMaximumTextureLevel()) - { - return gl::error(GL_INVALID_VALUE); - } - - switch (format) { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (!context->supportsDXT1Textures()) - { - return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (!context->supportsDXT3Textures()) - { - return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (!context->supportsDXT5Textures()) - { - return gl::error(GL_INVALID_ENUM); // in this case, it's as though the internal format switch failed - } - break; - default: UNREACHABLE(); - } - - if (imageSize != gl::ComputeCompressedSize(width, height, format)) - { - return gl::error(GL_INVALID_VALUE); - } - - if (xoffset % 4 != 0 || yoffset % 4 != 0) - { - return gl::error(GL_INVALID_OPERATION); // we wait to check the offsets until this point, because the multiple-of-four restriction - // does not exist unless DXT textures are supported. - } - - if (target == GL_TEXTURE_2D) + case GL_TEXTURE_2D: { gl::Texture2D *texture = context->getTexture2D(); - if (validateSubImageParams2D(true, width, height, xoffset, yoffset, level, format, GL_NONE, texture)) - { - texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data); - } + texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, data); } - else if (gl::IsCubemapTextureTarget(target)) + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { gl::TextureCubeMap *texture = context->getTextureCubeMap(); - if (validateSubImageParamsCube(true, width, height, xoffset, yoffset, target, level, format, GL_NONE, texture)) - { - texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data); - } - } - else - { - UNREACHABLE(); + texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, data); } + break; + + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border) @@ -1259,194 +812,51 @@ void __stdcall glCopyTexImage2D(GLenum target, GLint level, GLenum internalforma "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)", target, level, internalformat, x, y, width, height, border); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (!validImageSize(level, width, height)) + if (context->getClientVersion() < 3 && + !ValidateES2CopyTexImageParameters(context, target, level, internalformat, false, + 0, 0, x, y, width, height, border)) { - return gl::error(GL_INVALID_VALUE); + return; } - if (border != 0) + if (context->getClientVersion() >= 3 && + !ValidateES3CopyTexImageParameters(context, target, level, internalformat, false, + 0, 0, 0, x, y, width, height, border)) { - return gl::error(GL_INVALID_VALUE); + return; } - gl::Context *context = gl::getNonLostContext(); + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - if (context) + switch (target) { - if (level > context->getMaximumTextureLevel()) - { - return gl::error(GL_INVALID_VALUE); - } - - switch (target) - { - case GL_TEXTURE_2D: - if (width > (context->getMaximumTextureDimension() >> level) || - height > (context->getMaximumTextureDimension() >> level)) - { - return gl::error(GL_INVALID_VALUE); - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (width != height) - { - return gl::error(GL_INVALID_VALUE); - } - - if (width > (context->getMaximumCubeTextureDimension() >> level) || - height > (context->getMaximumCubeTextureDimension() >> level)) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - gl::Framebuffer *framebuffer = context->getReadFramebuffer(); - - if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) - { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); - } - - if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::Renderbuffer *source = framebuffer->getReadColorbuffer(); - GLenum colorbufferFormat = source->getInternalFormat(); - - // [OpenGL ES 2.0.24] table 3.9 - switch (internalformat) - { - case GL_ALPHA: - if (colorbufferFormat != GL_ALPHA8_EXT && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - case GL_LUMINANCE: - case GL_RGB: - if (colorbufferFormat != GL_RGB565 && - colorbufferFormat != GL_RGB8_OES && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - case GL_LUMINANCE_ALPHA: - case GL_RGBA: - if (colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_BGRA8_EXT && - colorbufferFormat != GL_RGBA8_OES) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (context->supportsDXT1Textures()) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (context->supportsDXT3Textures()) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (context->supportsDXT5Textures()) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_DEPTH_COMPONENT: - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT32_OES: - case GL_DEPTH_STENCIL_OES: - case GL_DEPTH24_STENCIL8_OES: - if (context->supportsDepthTextures()) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - default: - return gl::error(GL_INVALID_ENUM); - } - - if (target == GL_TEXTURE_2D) + case GL_TEXTURE_2D: { gl::Texture2D *texture = context->getTexture2D(); - - if (!texture) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (texture->isImmutable()) - { - return gl::error(GL_INVALID_OPERATION); - } - texture->copyImage(level, internalformat, x, y, width, height, framebuffer); } - else if (gl::IsCubemapTextureTarget(target)) + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { gl::TextureCubeMap *texture = context->getTextureCubeMap(); - - if (!texture) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (texture->isImmutable()) - { - return gl::error(GL_INVALID_OPERATION); - } - texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer); } - else UNREACHABLE(); + break; + + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) @@ -1455,148 +865,61 @@ void __stdcall glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GL "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", target, level, xoffset, yoffset, x, y, width, height); - try - { - if (!gl::IsInternalTextureTarget(target)) - { - return gl::error(GL_INVALID_ENUM); - } - - if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) - { - return gl::error(GL_INVALID_VALUE); - } + gl::Context *context = gl::getNonLostContext(); - if (std::numeric_limits::max() - xoffset < width || std::numeric_limits::max() - yoffset < height) + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true, + xoffset, yoffset, x, y, width, height, 0)) { - return gl::error(GL_INVALID_VALUE); + return; } - if (width == 0 || height == 0) + if (context->getClientVersion() >= 3 && + !ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, + xoffset, yoffset, 0, x, y, width, height, 0)) { return; } - gl::Context *context = gl::getNonLostContext(); + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); - if (context) + switch (target) { - if (level > context->getMaximumTextureLevel()) + case GL_TEXTURE_2D: { - return gl::error(GL_INVALID_VALUE); - } - - gl::Framebuffer *framebuffer = context->getReadFramebuffer(); - - if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) - { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION); - } - - if (context->getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::Renderbuffer *source = framebuffer->getReadColorbuffer(); - GLenum colorbufferFormat = source->getInternalFormat(); - gl::Texture *texture = NULL; - GLenum textureFormat = GL_RGBA; - - if (target == GL_TEXTURE_2D) - { - gl::Texture2D *tex2d = context->getTexture2D(); - - if (!validateSubImageParams2D(false, width, height, xoffset, yoffset, level, GL_NONE, GL_NONE, tex2d)) - { - return; // error already registered by validateSubImageParams - } - textureFormat = gl::ExtractFormat(tex2d->getInternalFormat(level)); - texture = tex2d; - } - else if (gl::IsCubemapTextureTarget(target)) - { - gl::TextureCubeMap *texcube = context->getTextureCubeMap(); - - if (!validateSubImageParamsCube(false, width, height, xoffset, yoffset, target, level, GL_NONE, GL_NONE, texcube)) - { - return; // error already registered by validateSubImageParams - } - textureFormat = gl::ExtractFormat(texcube->getInternalFormat(target, level)); - texture = texcube; + gl::Texture2D *texture = context->getTexture2D(); + texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); } - else UNREACHABLE(); + break; - // [OpenGL ES 2.0.24] table 3.9 - switch (textureFormat) + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { - case GL_ALPHA: - if (colorbufferFormat != GL_ALPHA8_EXT && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - case GL_LUMINANCE: - case GL_RGB: - if (colorbufferFormat != GL_RGB565 && - colorbufferFormat != GL_RGB8_OES && - colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - case GL_LUMINANCE_ALPHA: - case GL_RGBA: - if (colorbufferFormat != GL_RGBA4 && - colorbufferFormat != GL_RGB5_A1 && - colorbufferFormat != GL_RGBA8_OES) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - return gl::error(GL_INVALID_OPERATION); - case GL_DEPTH_COMPONENT: - case GL_DEPTH_STENCIL_OES: - return gl::error(GL_INVALID_OPERATION); - default: - return gl::error(GL_INVALID_OPERATION); + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer); } + break; - texture->copySubImage(target, level, xoffset, yoffset, x, y, width, height, framebuffer); + default: + return gl::error(GL_INVALID_ENUM); } } - - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } GLuint __stdcall glCreateProgram(void) { EVENT("()"); - try - { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - return context->createProgram(); - } - } - catch(std::bad_alloc&) + gl::Context *context = gl::getNonLostContext(); + if (context) { - return gl::error(GL_OUT_OF_MEMORY, 0); + return context->createProgram(); } return 0; @@ -1606,26 +929,19 @@ GLuint __stdcall glCreateShader(GLenum type) { EVENT("(GLenum type = 0x%X)", type); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + switch (type) { - switch (type) - { - case GL_FRAGMENT_SHADER: - case GL_VERTEX_SHADER: - return context->createShader(type); - default: - return gl::error(GL_INVALID_ENUM, 0); - } + case GL_FRAGMENT_SHADER: + case GL_VERTEX_SHADER: + return context->createShader(type); + default: + return gl::error(GL_INVALID_ENUM, 0); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, 0); - } return 0; } @@ -1634,29 +950,22 @@ void __stdcall glCullFace(GLenum mode) { EVENT("(GLenum mode = 0x%X)", mode); - try + switch (mode) { - switch (mode) + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setCullMode(mode); - } + if (context) + { + context->getState().setCullMode(mode); } - break; - default: - return gl::error(GL_INVALID_ENUM); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + break; + default: + return gl::error(GL_INVALID_ENUM); } } @@ -1664,119 +973,91 @@ void __stdcall glDeleteBuffers(GLsizei n, const GLuint* buffers) { EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - context->deleteBuffer(buffers[i]); - } + context->deleteBuffer(buffers[i]); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDeleteFencesNV(GLsizei n, const GLuint* fences) { EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - context->deleteFence(fences[i]); - } + context->deleteFenceNV(fences[i]); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) { EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) + if (framebuffers[i] != 0) { - if (framebuffers[i] != 0) - { - context->deleteFramebuffer(framebuffers[i]); - } + context->deleteFramebuffer(framebuffers[i]); } } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDeleteProgram(GLuint program) { EVENT("(GLuint program = %d)", program); - try + if (program == 0) { - if (program == 0) - { - return; - } + return; + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!context->getProgram(program)) { - if (!context->getProgram(program)) + if(context->getShader(program)) { - if(context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); } - - context->deleteProgram(program); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->deleteProgram(program); } } @@ -1784,89 +1065,68 @@ void __stdcall glDeleteQueriesEXT(GLsizei n, const GLuint *ids) { EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - context->deleteQuery(ids[i]); - } + context->deleteQuery(ids[i]); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) { EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - context->deleteRenderbuffer(renderbuffers[i]); - } + context->deleteRenderbuffer(renderbuffers[i]); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDeleteShader(GLuint shader) { EVENT("(GLuint shader = %d)", shader); - try + if (shader == 0) { - if (shader == 0) - { - return; - } + return; + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!context->getShader(shader)) { - if (!context->getShader(shader)) + if(context->getProgram(shader)) { - if(context->getProgram(shader)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); } - - context->deleteShader(shader); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->deleteShader(shader); } } @@ -1874,82 +1134,61 @@ void __stdcall glDeleteTextures(GLsizei n, const GLuint* textures) { EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) + if (textures[i] != 0) { - if (textures[i] != 0) - { - context->deleteTexture(textures[i]); - } + context->deleteTexture(textures[i]); } } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glDepthFunc(GLenum func) { EVENT("(GLenum func = 0x%X)", func); - try + switch (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); - } + 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(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setDepthFunc(func); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setDepthFunc(func); } } void __stdcall glDepthMask(GLboolean flag) { - EVENT("(GLboolean flag = %d)", flag); + EVENT("(GLboolean flag = %u)", flag); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setDepthMask(flag != GL_FALSE); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setDepthMask(flag != GL_FALSE); } } @@ -1957,18 +1196,11 @@ void __stdcall glDepthRangef(GLclampf zNear, GLclampf zFar) { EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setDepthRange(zNear, zFar); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setDepthRange(zNear, zFar); } } @@ -1976,52 +1208,45 @@ void __stdcall glDetachShader(GLuint program, GLuint shader) { EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); - if (context) - { + gl::Program *programObject = context->getProgram(program); + gl::Shader *shaderObject = context->getShader(shader); - gl::Program *programObject = context->getProgram(program); - gl::Shader *shaderObject = context->getShader(shader); - - if (!programObject) + if (!programObject) + { + gl::Shader *shaderByProgramHandle; + shaderByProgramHandle = context->getShader(program); + if (!shaderByProgramHandle) { - gl::Shader *shaderByProgramHandle; - shaderByProgramHandle = context->getShader(program); - if (!shaderByProgramHandle) - { - return gl::error(GL_INVALID_VALUE); - } - else - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_VALUE); } - - if (!shaderObject) + else { - gl::Program *programByShaderHandle = context->getProgram(shader); - if (!programByShaderHandle) - { - return gl::error(GL_INVALID_VALUE); - } - else - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION); } + } - if (!programObject->detachShader(shaderObject)) + if (!shaderObject) + { + gl::Program *programByShaderHandle = context->getProgram(shader); + if (!programByShaderHandle) + { + return gl::error(GL_INVALID_VALUE); + } + else { return gl::error(GL_INVALID_OPERATION); } } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + if (!programObject->detachShader(shaderObject)) + { + return gl::error(GL_INVALID_OPERATION); + } } } @@ -2029,31 +1254,16 @@ void __stdcall glDisable(GLenum cap) { EVENT("(GLenum cap = 0x%X)", cap); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!ValidCap(context, cap)) { - switch (cap) - { - case GL_CULL_FACE: context->setCullFace(false); break; - case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFill(false); break; - case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(false); break; - case GL_SAMPLE_COVERAGE: context->setSampleCoverage(false); break; - case GL_SCISSOR_TEST: context->setScissorTest(false); break; - case GL_STENCIL_TEST: context->setStencilTest(false); break; - case GL_DEPTH_TEST: context->setDepthTest(false); break; - case GL_BLEND: context->setBlend(false); break; - case GL_DITHER: context->setDither(false); break; - default: - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_ENUM); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->getState().setEnableFeature(cap, false); } } @@ -2061,23 +1271,16 @@ void __stdcall glDisableVertexAttribArray(GLuint index) { EVENT("(GLuint index = %d)", index); - try + if (index >= gl::MAX_VERTEX_ATTRIBS) { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setEnableVertexAttribArray(index, false); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setEnableVertexAttribArray(index, false); } } @@ -2085,23 +1288,16 @@ void __stdcall glDrawArrays(GLenum mode, GLint first, GLsizei count) { EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (count < 0 || first < 0) + if (!ValidateDrawArrays(context, mode, first, count)) { - return gl::error(GL_INVALID_VALUE); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->drawArrays(mode, first, count, 0); - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + context->drawArrays(mode, first, count, 0); } } @@ -2109,26 +1305,16 @@ 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); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (count < 0 || first < 0 || primcount < 0) + if (!ValidateDrawArraysInstanced(context, mode, first, count, primcount)) { - return gl::error(GL_INVALID_VALUE); + return; } - if (primcount > 0) - { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->drawArrays(mode, first, count, primcount); - } - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + context->drawArrays(mode, first, count, primcount); } } @@ -2137,38 +1323,16 @@ void __stdcall glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLv EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)", mode, count, type, indices); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (count < 0) + if (!ValidateDrawElements(context, mode, count, type, indices)) { - return gl::error(GL_INVALID_VALUE); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT: - break; - case GL_UNSIGNED_INT: - if (!context->supports32bitIndices()) - { - return gl::error(GL_INVALID_ENUM); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - context->drawElements(mode, count, type, indices, 0); - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + context->drawElements(mode, count, type, indices, 0); } } @@ -2177,41 +1341,16 @@ void __stdcall glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum t EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei primcount = %d)", mode, count, type, indices, primcount); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (count < 0 || primcount < 0) + if (!ValidateDrawElementsInstanced(context, mode, count, type, indices, primcount)) { - return gl::error(GL_INVALID_VALUE); + return; } - if (primcount > 0) - { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - switch (type) - { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT: - break; - case GL_UNSIGNED_INT: - if (!context->supports32bitIndices()) - { - return gl::error(GL_INVALID_ENUM); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } - - context->drawElements(mode, count, type, indices, primcount); - } - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + context->drawElements(mode, count, type, indices, primcount); } } @@ -2219,31 +1358,16 @@ void __stdcall glEnable(GLenum cap) { EVENT("(GLenum cap = 0x%X)", cap); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!ValidCap(context, cap)) { - switch (cap) - { - case GL_CULL_FACE: context->setCullFace(true); break; - case GL_POLYGON_OFFSET_FILL: context->setPolygonOffsetFill(true); break; - case GL_SAMPLE_ALPHA_TO_COVERAGE: context->setSampleAlphaToCoverage(true); break; - case GL_SAMPLE_COVERAGE: context->setSampleCoverage(true); break; - case GL_SCISSOR_TEST: context->setScissorTest(true); break; - case GL_STENCIL_TEST: context->setStencilTest(true); break; - case GL_DEPTH_TEST: context->setDepthTest(true); break; - case GL_BLEND: context->setBlend(true); break; - case GL_DITHER: context->setDither(true); break; - default: - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_ENUM); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->getState().setEnableFeature(cap, true); } } @@ -2251,23 +1375,16 @@ void __stdcall glEnableVertexAttribArray(GLuint index) { EVENT("(GLuint index = %d)", index); - try + if (index >= gl::MAX_VERTEX_ATTRIBS) { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setEnableVertexAttribArray(index, true); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setEnableVertexAttribArray(index, true); } } @@ -2275,27 +1392,16 @@ void __stdcall glEndQueryEXT(GLenum target) { EVENT("GLenum target = 0x%X)", target); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - switch (target) + if (!ValidateEndQuery(context, target)) { - case GL_ANY_SAMPLES_PASSED_EXT: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: - break; - default: - return gl::error(GL_INVALID_ENUM); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - context->endQuery(target); - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + context->endQuery(target); } } @@ -2303,25 +1409,23 @@ void __stdcall glFinishFenceNV(GLuint fence) { EVENT("(GLuint fence = %d)", fence); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::FenceNV *fenceObject = context->getFenceNV(fence); - if (context) + if (fenceObject == NULL) { - gl::Fence* fenceObject = context->getFence(fence); - - if (fenceObject == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION); + } - fenceObject->finishFence(); + if (fenceObject->isFence() != GL_TRUE) + { + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + fenceObject->finishFence(); } } @@ -2329,18 +1433,11 @@ void __stdcall glFinish(void) { EVENT("()"); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->sync(true); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->sync(true); } } @@ -2348,18 +1445,11 @@ void __stdcall glFlush(void) { EVENT("()"); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->sync(false); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->sync(false); } } @@ -2368,67 +1458,47 @@ 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); - try + if (!gl::ValidFramebufferTarget(target) || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)) { - if ((target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) - || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0)) - { - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_ENUM); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!gl::ValidateFramebufferRenderbufferParameters(context, target, attachment, renderbuffertarget, renderbuffer)) { - gl::Framebuffer *framebuffer = NULL; - GLuint framebufferHandle = 0; - if (target == GL_READ_FRAMEBUFFER_ANGLE) - { - framebuffer = context->getReadFramebuffer(); - framebufferHandle = context->getReadFramebufferHandle(); - } - else - { - framebuffer = context->getDrawFramebuffer(); - framebufferHandle = context->getDrawFramebufferHandle(); - } - - if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0)) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) - { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + return; + } - if (colorAttachment >= context->getMaximumRenderTargets()) - { - return gl::error(GL_INVALID_VALUE); - } + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); - framebuffer->setColorbuffer(colorAttachment, GL_RENDERBUFFER, renderbuffer); - } - else + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + framebuffer->setColorbuffer(colorAttachment, GL_RENDERBUFFER, renderbuffer, 0, 0); + } + else + { + switch (attachment) { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: - framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer); - break; - case GL_STENCIL_ATTACHMENT: - framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer); - break; - default: - return gl::error(GL_INVALID_ENUM); - } + case GL_DEPTH_ATTACHMENT: + framebuffer->setDepthbuffer(GL_RENDERBUFFER, renderbuffer, 0, 0); + break; + case GL_STENCIL_ATTACHMENT: + framebuffer->setStencilbuffer(GL_RENDERBUFFER, renderbuffer, 0, 0); + break; + case GL_DEPTH_STENCIL_ATTACHMENT: + framebuffer->setDepthStencilBuffer(GL_RENDERBUFFER, renderbuffer, 0, 0); + break; + default: + UNREACHABLE(); + break; } } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) @@ -2436,167 +1506,57 @@ void __stdcall glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum t EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, " "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level); - try + gl::Context *context = gl::getNonLostContext(); + if (context) { - if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) + if (!ValidateFramebufferTexture2D(context, target, attachment, textarget, texture, level)) { - return gl::error(GL_INVALID_ENUM); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (texture == 0) { - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) - { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); - - if (colorAttachment >= context->getMaximumRenderTargets()) - { - return gl::error(GL_INVALID_VALUE); - } - } - else - { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: - case GL_STENCIL_ATTACHMENT: - break; - default: - return gl::error(GL_INVALID_ENUM); - } - } - - if (texture == 0) - { - textarget = GL_NONE; - } - else - { - gl::Texture *tex = context->getTexture(texture); - - if (tex == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (textarget) - { - case GL_TEXTURE_2D: - { - if (tex->getTarget() != GL_TEXTURE_2D) - { - return gl::error(GL_INVALID_OPERATION); - } - gl::Texture2D *tex2d = static_cast(tex); - if (tex2d->isCompressed(0)) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - } - - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - { - if (tex->getTarget() != GL_TEXTURE_CUBE_MAP) - { - return gl::error(GL_INVALID_OPERATION); - } - gl::TextureCubeMap *texcube = static_cast(tex); - if (texcube->isCompressed(textarget, level)) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - } - - default: - return gl::error(GL_INVALID_ENUM); - } - - if (level != 0) - { - return gl::error(GL_INVALID_VALUE); - } - } - - gl::Framebuffer *framebuffer = NULL; - GLuint framebufferHandle = 0; - if (target == GL_READ_FRAMEBUFFER_ANGLE) - { - framebuffer = context->getReadFramebuffer(); - framebufferHandle = context->getReadFramebufferHandle(); - } - else - { - framebuffer = context->getDrawFramebuffer(); - framebufferHandle = context->getDrawFramebufferHandle(); - } - - if (framebufferHandle == 0 || !framebuffer) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) - { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + textarget = GL_NONE; + } - if (colorAttachment >= context->getMaximumRenderTargets()) - { - return gl::error(GL_INVALID_VALUE); - } + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); - framebuffer->setColorbuffer(colorAttachment, textarget, texture); - } - else + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + framebuffer->setColorbuffer(colorAttachment, textarget, texture, level, 0); + } + else + { + switch (attachment) { - switch (attachment) - { - case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture); break; - case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture); break; - } + case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level, 0); break; + case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level, 0); break; + case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture, level, 0); break; } } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glFrontFace(GLenum mode) { EVENT("(GLenum mode = 0x%X)", mode); - try + switch (mode) { - switch (mode) + case GL_CW: + case GL_CCW: { - case GL_CW: - case GL_CCW: - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setFrontFace(mode); - } + if (context) + { + context->getState().setFrontFace(mode); } - break; - default: - return gl::error(GL_INVALID_ENUM); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + break; + default: + return gl::error(GL_INVALID_ENUM); } } @@ -2604,79 +1564,87 @@ void __stdcall glGenBuffers(GLsizei n, GLuint* buffers) { EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - buffers[i] = context->createBuffer(); - } + buffers[i] = context->createBuffer(); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGenerateMipmap(GLenum target) { EVENT("(GLenum target = 0x%X)", target); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (!ValidTextureTarget(context, target)) + { + return gl::error(GL_INVALID_ENUM); + } - if (context) + gl::Texture *texture = context->getTargetTexture(target); + + if (texture == NULL) { - switch (target) - { - case GL_TEXTURE_2D: - { - gl::Texture2D *tex2d = context->getTexture2D(); + return gl::error(GL_INVALID_OPERATION); + } - if (tex2d->isCompressed(0)) - { - return gl::error(GL_INVALID_OPERATION); - } - if (tex2d->isDepth(0)) - { - return gl::error(GL_INVALID_OPERATION); - } + GLenum internalFormat = texture->getBaseLevelInternalFormat(); + const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat); - tex2d->generateMipmaps(); - break; - } + // GenerateMipmap should not generate an INVALID_OPERATION for textures created with + // unsized formats or that are color renderable and filterable. Since we do not track if + // the texture was created with sized or unsized format (only sized formats are stored), + // it is not possible to make sure the the LUMA formats can generate mipmaps (they should + // be able to) because they aren't color renderable. Simply do a special case for LUMA + // textures since they're the only texture format that can be created with unsized formats + // that is not color renderable. New unsized formats are unlikely to be added, since ES2 + // was the last version to use add them. + bool isLUMA = internalFormat == GL_LUMINANCE8_EXT || + internalFormat == GL_LUMINANCE8_ALPHA8_EXT || + internalFormat == GL_ALPHA8_EXT; - case GL_TEXTURE_CUBE_MAP: - { - gl::TextureCubeMap *texcube = context->getTextureCubeMap(); + if (gl::GetDepthBits(internalFormat) > 0 || gl::GetStencilBits(internalFormat) > 0 || !formatCaps.filterable || + (!formatCaps.renderable && !isLUMA) || gl::IsFormatCompressed(internalFormat)) + { + return gl::error(GL_INVALID_OPERATION); + } - if (texcube->isCompressed(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)) - { - return gl::error(GL_INVALID_OPERATION); - } + // GL_EXT_sRGB does not support mipmap generation on sRGB textures + if (context->getClientVersion() == 2 && gl::GetColorEncoding(internalFormat) == GL_SRGB) + { + return gl::error(GL_INVALID_OPERATION); + } - texcube->generateMipmaps(); - break; - } + // 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); + } - default: - return gl::error(GL_INVALID_ENUM); + // Cube completeness check + if (target == GL_TEXTURE_CUBE_MAP) + { + gl::TextureCubeMap *textureCube = static_cast(texture); + if (!textureCube->isCubeComplete()) + { + return gl::error(GL_INVALID_OPERATION); } } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + texture->generateMipmaps(); } } @@ -2684,135 +1652,100 @@ void __stdcall glGenFencesNV(GLsizei n, GLuint* fences) { EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - fences[i] = context->createFence(); - } + fences[i] = context->createFenceNV(); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGenFramebuffers(GLsizei n, GLuint* framebuffers) { EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - framebuffers[i] = context->createFramebuffer(); - } + framebuffers[i] = context->createFramebuffer(); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGenQueriesEXT(GLsizei n, GLuint* ids) { EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { if (n < 0) { return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + for (GLsizei i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - ids[i] = context->createQuery(); - } + ids[i] = context->createQuery(); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGenRenderbuffers(GLsizei n, GLuint* renderbuffers) { EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - renderbuffers[i] = context->createRenderbuffer(); - } + renderbuffers[i] = context->createRenderbuffer(); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGenTextures(GLsizei n, GLuint* textures) { - EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures); + EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures); - try + if (n < 0) { - if (n < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + for (int i = 0; i < n; i++) { - for (int i = 0; i < n; i++) - { - textures[i] = context->createTexture(); - } + textures[i] = context->createTexture(); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) @@ -2821,42 +1754,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); - try + if (bufsize < 0) { - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); + if (context) + { + gl::Program *programObject = context->getProgram(program); - if (!programObject) + if (!programObject) + { + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); } - - if (index >= (GLuint)programObject->getActiveAttributeCount()) + else { return gl::error(GL_INVALID_VALUE); } + } - programObject->getActiveAttribute(index, bufsize, length, size, type, name); + if (index >= (GLuint)programObject->getActiveAttributeCount()) + { + return gl::error(GL_INVALID_VALUE); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + programObject->getActiveAttribute(index, bufsize, length, size, type, name); } } @@ -2866,42 +1792,35 @@ 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); - try + if (bufsize < 0) { - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); + if (context) + { + gl::Program *programObject = context->getProgram(program); - if (!programObject) + if (!programObject) + { + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); } - - if (index >= (GLuint)programObject->getActiveUniformCount()) + else { return gl::error(GL_INVALID_VALUE); } + } - programObject->getActiveUniform(index, bufsize, length, size, type, name); + if (index >= (GLuint)programObject->getActiveUniformCount()) + { + return gl::error(GL_INVALID_VALUE); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + programObject->getActiveUniform(index, bufsize, length, size, type, name); } } @@ -2910,37 +1829,30 @@ 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); - try + if (maxcount < 0) { - if (maxcount < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); + if (context) + { + gl::Program *programObject = context->getProgram(program); - if (!programObject) + if (!programObject) + { + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); } - - return programObject->getAttachedShaders(maxcount, count, shaders); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + return programObject->getAttachedShaders(maxcount, count, shaders); } } @@ -2948,39 +1860,32 @@ int __stdcall glGetAttribLocation(GLuint program, const GLchar* name) { EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { + if (context) + { - gl::Program *programObject = context->getProgram(program); + gl::Program *programObject = context->getProgram(program); - if (!programObject) + if (!programObject) + { + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION, -1); - } - else - { - return gl::error(GL_INVALID_VALUE, -1); - } + return gl::error(GL_INVALID_OPERATION, -1); } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programObject->isLinked() || !programBinary) + else { - return gl::error(GL_INVALID_OPERATION, -1); + return gl::error(GL_INVALID_VALUE, -1); } + } - return programBinary->getAttributeLocation(name); + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programObject->isLinked() || !programBinary) + { + return gl::error(GL_INVALID_OPERATION, -1); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, -1); + + return programBinary->getAttributeLocation(name); } return -1; @@ -2990,62 +1895,25 @@ void __stdcall glGetBooleanv(GLenum pname, GLboolean* params) { EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) { - if (!(context->getBooleanv(pname, params))) - { - GLenum nativeType; - unsigned int numParams = 0; - if (!context->getQueryParameterInfo(pname, &nativeType, &numParams)) - return gl::error(GL_INVALID_ENUM); - - if (numParams == 0) - return; // it is known that the pname is valid, but there are no parameters to return - - if (nativeType == GL_FLOAT) - { - GLfloat *floatParams = NULL; - floatParams = new GLfloat[numParams]; - - context->getFloatv(pname, floatParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - if (floatParams[i] == 0.0f) - params[i] = GL_FALSE; - else - params[i] = GL_TRUE; - } - - delete [] floatParams; - } - else if (nativeType == GL_INT) - { - GLint *intParams = NULL; - intParams = new GLint[numParams]; - - context->getIntegerv(pname, intParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - if (intParams[i] == 0) - params[i] = GL_FALSE; - else - params[i] = GL_TRUE; - } + return; + } - delete [] intParams; - } - } + if (nativeType == GL_BOOL) + { + context->getBooleanv(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -3053,47 +1921,51 @@ 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); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (!gl::ValidBufferTarget(context, target)) + { + return gl::error(GL_INVALID_ENUM); + } - if (context) + if (!gl::ValidBufferParameter(context, pname)) { - gl::Buffer *buffer; + return gl::error(GL_INVALID_ENUM); + } - switch (target) - { - case GL_ARRAY_BUFFER: - buffer = context->getArrayBuffer(); - break; - case GL_ELEMENT_ARRAY_BUFFER: - buffer = context->getElementArrayBuffer(); - break; - default: return gl::error(GL_INVALID_ENUM); - } + gl::Buffer *buffer = context->getState().getTargetBuffer(target); - if (!buffer) - { - // A null buffer means that "0" is bound to the requested buffer target - return gl::error(GL_INVALID_OPERATION); - } + if (!buffer) + { + // A null buffer means that "0" is bound to the requested buffer target + return gl::error(GL_INVALID_OPERATION); + } - switch (pname) - { - case GL_BUFFER_USAGE: - *params = buffer->usage(); - break; - case GL_BUFFER_SIZE: - *params = buffer->size(); - break; - default: return gl::error(GL_INVALID_ENUM); - } + switch (pname) + { + case GL_BUFFER_USAGE: + *params = static_cast(buffer->getUsage()); + break; + case GL_BUFFER_SIZE: + *params = gl::clampCast(buffer->getSize()); + break; + case GL_BUFFER_ACCESS_FLAGS: + *params = buffer->getAccessFlags(); + break; + case GL_BUFFER_MAPPED: + *params = static_cast(buffer->isMapped()); + break; + case GL_BUFFER_MAP_OFFSET: + *params = gl::clampCast(buffer->getMapOffset()); + break; + case GL_BUFFER_MAP_LENGTH: + *params = gl::clampCast(buffer->getMapLength()); + break; + default: UNREACHABLE(); break; } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } GLenum __stdcall glGetError(void) @@ -3114,26 +1986,33 @@ 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); - try - { - - gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Fence *fenceObject = context->getFence(fence); + gl::Context *context = gl::getNonLostContext(); - if (fenceObject == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } + if (context) + { + gl::FenceNV *fenceObject = context->getFenceNV(fence); - fenceObject->getFenceiv(pname, params); + if (fenceObject == NULL) + { + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + if (fenceObject->isFence() != GL_TRUE) + { + return gl::error(GL_INVALID_OPERATION); + } + + switch (pname) + { + case GL_FENCE_STATUS_NV: + case GL_FENCE_CONDITION_NV: + break; + + default: return gl::error(GL_INVALID_ENUM); + } + + params[0] = fenceObject->getFencei(pname); } } @@ -3141,59 +2020,25 @@ void __stdcall glGetFloatv(GLenum pname, GLfloat* params) { EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) { - if (!(context->getFloatv(pname, params))) - { - GLenum nativeType; - unsigned int numParams = 0; - if (!context->getQueryParameterInfo(pname, &nativeType, &numParams)) - return gl::error(GL_INVALID_ENUM); - - if (numParams == 0) - return; // it is known that the pname is valid, but that there are no parameters to return. - - if (nativeType == GL_BOOL) - { - GLboolean *boolParams = NULL; - boolParams = new GLboolean[numParams]; - - context->getBooleanv(pname, boolParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - if (boolParams[i] == GL_FALSE) - params[i] = 0.0f; - else - params[i] = 1.0f; - } - - delete [] boolParams; - } - else if (nativeType == GL_INT) - { - GLint *intParams = NULL; - intParams = new GLint[numParams]; - - context->getIntegerv(pname, intParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - params[i] = (GLfloat)intParams[i]; - } + return; + } - delete [] intParams; - } - } + if (nativeType == GL_FLOAT) + { + context->getFloatv(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -3202,219 +2047,313 @@ void __stdcall glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attac EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, attachment, pname, params); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (!gl::ValidFramebufferTarget(target)) + { + return gl::error(GL_INVALID_ENUM); + } - if (context) + int clientVersion = context->getClientVersion(); + + switch (pname) { - if (target != GL_FRAMEBUFFER && target != GL_DRAW_FRAMEBUFFER_ANGLE && target != GL_READ_FRAMEBUFFER_ANGLE) + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + break; + case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: + if (clientVersion < 3 && !context->getExtensions().sRGB) { return gl::error(GL_INVALID_ENUM); } - - gl::Framebuffer *framebuffer = NULL; - if (target == GL_READ_FRAMEBUFFER_ANGLE) + break; + case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: + case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: + if (clientVersion < 3) { - if(context->getReadFramebufferHandle() == 0) - { - return gl::error(GL_INVALID_OPERATION); - } - - framebuffer = context->getReadFramebuffer(); + return gl::error(GL_INVALID_ENUM); } - else - { - if (context->getDrawFramebufferHandle() == 0) - { - return gl::error(GL_INVALID_OPERATION); - } + break; + default: + return gl::error(GL_INVALID_ENUM); + } - framebuffer = context->getDrawFramebuffer(); + // Determine if the attachment is a valid enum + switch (attachment) + { + case GL_BACK: + case GL_FRONT: + case GL_DEPTH: + case GL_STENCIL: + case GL_DEPTH_STENCIL_ATTACHMENT: + if (clientVersion < 3) + { + return gl::error(GL_INVALID_ENUM); } + break; - GLenum attachmentType; - GLuint attachmentHandle; + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; - if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + default: + if (attachment < GL_COLOR_ATTACHMENT0_EXT || + (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments) { - const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + return gl::error(GL_INVALID_ENUM); + } + break; + } - if (colorAttachment >= context->getMaximumRenderTargets()) - { - return gl::error(GL_INVALID_ENUM); - } + GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); + gl::Framebuffer *framebuffer = context->getFramebuffer(framebufferHandle); - attachmentType = framebuffer->getColorbufferType(colorAttachment); - attachmentHandle = framebuffer->getColorbufferHandle(colorAttachment); + if (framebufferHandle == 0) + { + if (clientVersion < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + switch (attachment) + { + case GL_BACK: + case GL_DEPTH: + case GL_STENCIL: + break; + default: + return gl::error(GL_INVALID_OPERATION); + } + } + else + { + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + // Valid attachment query } else { switch (attachment) { case GL_DEPTH_ATTACHMENT: - attachmentType = framebuffer->getDepthbufferType(); - attachmentHandle = framebuffer->getDepthbufferHandle(); - break; case GL_STENCIL_ATTACHMENT: - attachmentType = framebuffer->getStencilbufferType(); - attachmentHandle = framebuffer->getStencilbufferHandle(); break; - default: return gl::error(GL_INVALID_ENUM); + case GL_DEPTH_STENCIL_ATTACHMENT: + if (framebuffer->hasValidDepthStencil()) + { + return gl::error(GL_INVALID_OPERATION); + } + break; + default: + return gl::error(GL_INVALID_OPERATION); } } + } - GLenum attachmentObjectType; // Type category - if (attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER) - { - attachmentObjectType = attachmentType; - } - else if (gl::IsInternalTextureTarget(attachmentType)) - { - attachmentObjectType = GL_TEXTURE; - } - else - { - UNREACHABLE(); - return; - } + GLenum attachmentType = GL_NONE; + GLuint attachmentHandle = 0; + GLuint attachmentLevel = 0; + GLuint attachmentLayer = 0; + + const gl::FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment); + + if (attachmentObject) + { + attachmentType = attachmentObject->type(); + attachmentHandle = attachmentObject->id(); + attachmentLevel = attachmentObject->mipLevel(); + attachmentLayer = attachmentObject->layer(); + } + + GLenum attachmentObjectType; // Type category + if (framebufferHandle == 0) + { + attachmentObjectType = GL_FRAMEBUFFER_DEFAULT; + } + else if (attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER) + { + attachmentObjectType = attachmentType; + } + else if (gl::ValidTexture2DDestinationTarget(context, attachmentType)) + { + attachmentObjectType = GL_TEXTURE; + } + else + { + UNREACHABLE(); + return; + } + + if (attachmentObjectType == GL_NONE) + { + // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE + // is NONE, then querying any other pname will generate INVALID_ENUM. + + // ES 3.0.2 spec pg 235 states that if the attachment type is none, + // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an + // INVALID_OPERATION for all other pnames switch (pname) { case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: *params = attachmentObjectType; break; + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: - if (attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE) + if (clientVersion < 3) { - *params = attachmentHandle; + return gl::error(GL_INVALID_ENUM); + } + *params = 0; + break; + + default: + if (clientVersion < 3) + { + return gl::error(GL_INVALID_ENUM); } else + { + gl::error(GL_INVALID_OPERATION); + } + } + } + else + { + ASSERT(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE || + attachmentObjectType == GL_FRAMEBUFFER_DEFAULT); + ASSERT(attachmentObject != NULL); + + switch (pname) + { + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: + *params = attachmentObjectType; + break; + + case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: + if (attachmentObjectType != GL_RENDERBUFFER && attachmentObjectType != GL_TEXTURE) { return gl::error(GL_INVALID_ENUM); } + *params = attachmentHandle; break; + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: - if (attachmentObjectType == GL_TEXTURE) + if (attachmentObjectType != GL_TEXTURE) { - *params = 0; // FramebufferTexture2D will not allow level to be set to anything else in GL ES 2.0 + return gl::error(GL_INVALID_ENUM); } - else + *params = attachmentLevel; + break; + + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: + if (attachmentObjectType != GL_TEXTURE) { return gl::error(GL_INVALID_ENUM); } + *params = gl::IsCubemapTextureTarget(attachmentType) ? attachmentType : 0; break; - case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: - if (attachmentObjectType == GL_TEXTURE) + + case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE: + *params = attachmentObject->getRedSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE: + *params = attachmentObject->getGreenSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE: + *params = attachmentObject->getBlueSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE: + *params = attachmentObject->getAlphaSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE: + *params = attachmentObject->getDepthSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE: + *params = attachmentObject->getStencilSize(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE: + if (attachment == GL_DEPTH_STENCIL) { - if (gl::IsCubemapTextureTarget(attachmentType)) - { - *params = attachmentType; - } - else - { - *params = 0; - } + gl::error(GL_INVALID_OPERATION); } - else + *params = attachmentObject->getComponentType(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING: + *params = attachmentObject->getColorEncoding(); + break; + + case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER: + if (attachmentObjectType != GL_TEXTURE) { return gl::error(GL_INVALID_ENUM); } + *params = attachmentLayer; break; + default: - return gl::error(GL_INVALID_ENUM); + UNREACHABLE(); + break; } } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } GLenum __stdcall glGetGraphicsResetStatusEXT(void) { EVENT("()"); - try - { - gl::Context *context = gl::getContext(); - - if (context) - { - return context->getResetStatus(); - } + gl::Context *context = gl::getContext(); - return GL_NO_ERROR; - } - catch(std::bad_alloc&) + if (context) { - return GL_OUT_OF_MEMORY; + return context->getResetStatus(); } + + return GL_NO_ERROR; } void __stdcall glGetIntegerv(GLenum pname, GLint* params) { EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + GLenum nativeType; + unsigned int numParams = 0; - if (context) + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) { - if (!(context->getIntegerv(pname, params))) - { - GLenum nativeType; - unsigned int numParams = 0; - if (!context->getQueryParameterInfo(pname, &nativeType, &numParams)) - return gl::error(GL_INVALID_ENUM); - - if (numParams == 0) - return; // it is known that pname is valid, but there are no parameters to return - - if (nativeType == GL_BOOL) - { - GLboolean *boolParams = NULL; - boolParams = new GLboolean[numParams]; - - context->getBooleanv(pname, boolParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - if (boolParams[i] == GL_FALSE) - params[i] = 0; - else - params[i] = 1; - } - - delete [] boolParams; - } - else if (nativeType == GL_FLOAT) - { - GLfloat *floatParams = NULL; - floatParams = new GLfloat[numParams]; - - context->getFloatv(pname, floatParams); - - for (unsigned int i = 0; i < numParams; ++i) - { - if (pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR) - { - params[i] = (GLint)(((GLfloat)(0xFFFFFFFF) * floatParams[i] - 1.0f) / 2.0f); - } - else - params[i] = (GLint)(floatParams[i] > 0.0f ? floor(floatParams[i] + 0.5) : ceil(floatParams[i] - 0.5)); - } + return; + } - delete [] floatParams; - } - } + if (nativeType == GL_INT) + { + context->getIntegerv(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -3422,59 +2361,80 @@ void __stdcall glGetProgramiv(GLuint program, GLenum pname, GLint* params) { EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } + if (context->getClientVersion() < 3) + { switch (pname) { - case GL_DELETE_STATUS: - *params = programObject->isFlaggedForDeletion(); - return; - case GL_LINK_STATUS: - *params = programObject->isLinked(); - return; - case GL_VALIDATE_STATUS: - *params = programObject->isValidated(); - return; - case GL_INFO_LOG_LENGTH: - *params = programObject->getInfoLogLength(); - return; - case GL_ATTACHED_SHADERS: - *params = programObject->getAttachedShadersCount(); - return; - case GL_ACTIVE_ATTRIBUTES: - *params = programObject->getActiveAttributeCount(); - return; - case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: - *params = programObject->getActiveAttributeMaxLength(); - return; - case GL_ACTIVE_UNIFORMS: - *params = programObject->getActiveUniformCount(); - return; - case GL_ACTIVE_UNIFORM_MAX_LENGTH: - *params = programObject->getActiveUniformMaxLength(); - return; - case GL_PROGRAM_BINARY_LENGTH_OES: - *params = programObject->getProgramBinaryLength(); - return; - default: + case GL_ACTIVE_UNIFORM_BLOCKS: + case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: + case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: + case GL_TRANSFORM_FEEDBACK_VARYINGS: + case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: return gl::error(GL_INVALID_ENUM); } } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + switch (pname) + { + case GL_DELETE_STATUS: + *params = programObject->isFlaggedForDeletion(); + return; + case GL_LINK_STATUS: + *params = programObject->isLinked(); + return; + case GL_VALIDATE_STATUS: + *params = programObject->isValidated(); + return; + case GL_INFO_LOG_LENGTH: + *params = programObject->getInfoLogLength(); + return; + case GL_ATTACHED_SHADERS: + *params = programObject->getAttachedShadersCount(); + return; + case GL_ACTIVE_ATTRIBUTES: + *params = programObject->getActiveAttributeCount(); + return; + case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: + *params = programObject->getActiveAttributeMaxLength(); + return; + case GL_ACTIVE_UNIFORMS: + *params = programObject->getActiveUniformCount(); + return; + case GL_ACTIVE_UNIFORM_MAX_LENGTH: + *params = programObject->getActiveUniformMaxLength(); + return; + case GL_PROGRAM_BINARY_LENGTH_OES: + *params = programObject->getProgramBinaryLength(); + return; + case GL_ACTIVE_UNIFORM_BLOCKS: + *params = programObject->getActiveUniformBlockCount(); + return; + case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH: + *params = programObject->getActiveUniformBlockMaxLength(); + break; + case GL_TRANSFORM_FEEDBACK_BUFFER_MODE: + *params = programObject->getTransformFeedbackBufferMode(); + break; + case GL_TRANSFORM_FEEDBACK_VARYINGS: + *params = programObject->getTransformFeedbackVaryingCount(); + break; + case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH: + *params = programObject->getTransformFeedbackVaryingMaxLength(); + break; + default: + return gl::error(GL_INVALID_ENUM); + } } } @@ -3483,30 +2443,23 @@ 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); - try + if (bufsize < 0) { - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - return gl::error(GL_INVALID_VALUE); - } + if (context) + { + gl::Program *programObject = context->getProgram(program); - programObject->getInfoLog(bufsize, length, infolog); + if (!programObject) + { + return gl::error(GL_INVALID_VALUE); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + programObject->getInfoLog(bufsize, length, infolog); } } @@ -3514,26 +2467,24 @@ 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); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { + if (!ValidQueryType(context, target)) + { + return gl::error(GL_INVALID_ENUM); + } + switch (pname) { case GL_CURRENT_QUERY_EXT: + params[0] = context->getState().getActiveQueryId(target); break; + default: return gl::error(GL_INVALID_ENUM); } - - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - params[0] = context->getActiveQuery(target); - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -3541,48 +2492,33 @@ 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); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - switch (pname) + gl::Query *queryObject = context->getQuery(id, false, GL_NONE); + + if (!queryObject) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (context->getState().getActiveQueryId(queryObject->getType()) == id) + { + return gl::error(GL_INVALID_OPERATION); + } + + switch(pname) { case GL_QUERY_RESULT_EXT: + params[0] = queryObject->getResult(); + break; case GL_QUERY_RESULT_AVAILABLE_EXT: + params[0] = queryObject->isResultAvailable(); break; default: return gl::error(GL_INVALID_ENUM); } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - gl::Query *queryObject = context->getQuery(id, false, GL_NONE); - - if (!queryObject) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (context->getActiveQuery(queryObject->getType()) == id) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch(pname) - { - case GL_QUERY_RESULT_EXT: - params[0] = queryObject->getResult(); - break; - case GL_QUERY_RESULT_AVAILABLE_EXT: - params[0] = queryObject->isResultAvailable(); - break; - default: - ASSERT(false); - } - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); } } @@ -3590,102 +2526,85 @@ 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); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (target != GL_RENDERBUFFER) { - if (target != GL_RENDERBUFFER) - { - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_ENUM); + } - if (context->getRenderbufferHandle() == 0) - { - return gl::error(GL_INVALID_OPERATION); - } + if (context->getState().getRenderbufferId() == 0) + { + return gl::error(GL_INVALID_OPERATION); + } - gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getRenderbufferHandle()); + gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getState().getRenderbufferId()); - switch (pname) + switch (pname) + { + case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break; + case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break; + case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break; + case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break; + case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break; + case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break; + case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break; + case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break; + case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break; + case GL_RENDERBUFFER_SAMPLES_ANGLE: + if (!context->getExtensions().framebufferMultisample) { - case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break; - case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break; - case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break; - case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break; - case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break; - case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break; - case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break; - case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break; - case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break; - case GL_RENDERBUFFER_SAMPLES_ANGLE: - if (context->getMaxSupportedSamples() != 0) - { - *params = renderbuffer->getSamples(); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - break; - default: return gl::error(GL_INVALID_ENUM); } + *params = renderbuffer->getSamples(); + break; + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGetShaderiv(GLuint shader, GLenum pname, GLint* params) { EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Shader *shaderObject = context->getShader(shader); - if (context) + if (!shaderObject) { - gl::Shader *shaderObject = context->getShader(shader); - - if (!shaderObject) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - switch (pname) - { - case GL_SHADER_TYPE: - *params = shaderObject->getType(); - return; - case GL_DELETE_STATUS: - *params = shaderObject->isFlaggedForDeletion(); - return; - case GL_COMPILE_STATUS: - *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE; - return; - case GL_INFO_LOG_LENGTH: - *params = shaderObject->getInfoLogLength(); - return; - case GL_SHADER_SOURCE_LENGTH: - *params = shaderObject->getSourceLength(); - return; - case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE: - *params = shaderObject->getTranslatedSourceLength(); - return; - default: - return gl::error(GL_INVALID_ENUM); - } + switch (pname) + { + case GL_SHADER_TYPE: + *params = shaderObject->getType(); + return; + case GL_DELETE_STATUS: + *params = shaderObject->isFlaggedForDeletion(); + return; + case GL_COMPILE_STATUS: + *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE; + return; + case GL_INFO_LOG_LENGTH: + *params = shaderObject->getInfoLogLength(); + return; + case GL_SHADER_SOURCE_LENGTH: + *params = shaderObject->getSourceLength(); + return; + case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE: + *params = shaderObject->getTranslatedSourceLength(); + return; + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog) @@ -3693,30 +2612,23 @@ 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); - try + if (bufsize < 0) { - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Context *context = gl::getNonLostContext(); + return gl::error(GL_INVALID_VALUE); + } - if (context) - { - gl::Shader *shaderObject = context->getShader(shader); + gl::Context *context = gl::getNonLostContext(); - if (!shaderObject) - { - return gl::error(GL_INVALID_VALUE); - } + if (context) + { + gl::Shader *shaderObject = context->getShader(shader); - shaderObject->getInfoLog(bufsize, length, infolog); + if (!shaderObject) + { + return gl::error(GL_INVALID_VALUE); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + shaderObject->getInfoLog(bufsize, length, infolog); } } @@ -3725,43 +2637,36 @@ 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); - try + switch (shadertype) { - switch (shadertype) - { - 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); - } + case GL_VERTEX_SHADER: + case GL_FRAGMENT_SHADER: + break; + default: + return gl::error(GL_INVALID_ENUM); } - catch(std::bad_alloc&) + + switch (precisiontype) { - return gl::error(GL_OUT_OF_MEMORY); + 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); } } @@ -3770,30 +2675,23 @@ 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); - try + if (bufsize < 0) { - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Context *context = gl::getNonLostContext(); + return gl::error(GL_INVALID_VALUE); + } - if (context) - { - gl::Shader *shaderObject = context->getShader(shader); + gl::Context *context = gl::getNonLostContext(); - if (!shaderObject) - { - return gl::error(GL_INVALID_OPERATION); - } + if (context) + { + gl::Shader *shaderObject = context->getShader(shader); - shaderObject->getSource(bufsize, length, source); + if (!shaderObject) + { + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + shaderObject->getSource(bufsize, length, source); } } @@ -3802,30 +2700,23 @@ 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); - try + if (bufsize < 0) { - if (bufsize < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Context *context = gl::getNonLostContext(); + return gl::error(GL_INVALID_VALUE); + } - if (context) - { - gl::Shader *shaderObject = context->getShader(shader); + gl::Context *context = gl::getNonLostContext(); - if (!shaderObject) - { - return gl::error(GL_INVALID_OPERATION); - } + if (context) + { + gl::Shader *shaderObject = context->getShader(shader); - shaderObject->getTranslatedSource(bufsize, length, source); + if (!shaderObject) + { + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + shaderObject->getTranslatedSource(bufsize, length, source); } } @@ -3833,29 +2724,36 @@ const GLubyte* __stdcall glGetString(GLenum name) { EVENT("(GLenum name = 0x%X)", name); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - switch (name) + switch (name) + { + case GL_VENDOR: + return (GLubyte*)"Google Inc."; + case GL_RENDERER: + return (GLubyte*)((context != NULL) ? context->getRendererString().c_str() : "ANGLE"); + case GL_VERSION: + if (context->getClientVersion() == 2) { - case GL_VENDOR: - return (GLubyte*)"Google Inc."; - case GL_RENDERER: - return (GLubyte*)((context != NULL) ? context->getRendererString() : "ANGLE"); - case GL_VERSION: return (GLubyte*)"OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")"; - case GL_SHADING_LANGUAGE_VERSION: + } + else + { + return (GLubyte*)"OpenGL ES 3.0 (ANGLE " ANGLE_VERSION_STRING ")"; + } + case GL_SHADING_LANGUAGE_VERSION: + if (context->getClientVersion() == 2) + { return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")"; - case GL_EXTENSIONS: - return (GLubyte*)((context != NULL) ? context->getExtensionString() : ""); - default: - return gl::error(GL_INVALID_ENUM, (GLubyte*)NULL); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, (GLubyte*)NULL); + else + { + return (GLubyte*)"OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")"; + } + case GL_EXTENSIONS: + return (GLubyte*)((context != NULL) ? context->getExtensionString().c_str() : ""); + default: + return gl::error(GL_INVALID_ENUM, (GLubyte*)NULL); } } @@ -3863,169 +2761,276 @@ 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); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Texture *texture = context->getTargetTexture(target); - if (context) + if (!texture) { - gl::Texture *texture; + return gl::error(GL_INVALID_ENUM); + } - switch (target) + switch (pname) + { + case GL_TEXTURE_MAG_FILTER: + *params = (GLfloat)texture->getSamplerState().magFilter; + break; + case GL_TEXTURE_MIN_FILTER: + *params = (GLfloat)texture->getSamplerState().minFilter; + break; + case GL_TEXTURE_WRAP_S: + *params = (GLfloat)texture->getSamplerState().wrapS; + break; + case GL_TEXTURE_WRAP_T: + *params = (GLfloat)texture->getSamplerState().wrapT; + break; + case GL_TEXTURE_WRAP_R: + if (context->getClientVersion() < 3) { - case GL_TEXTURE_2D: - texture = context->getTexture2D(); - break; - case GL_TEXTURE_CUBE_MAP: - texture = context->getTextureCubeMap(); - break; - default: return gl::error(GL_INVALID_ENUM); } - - switch (pname) + *params = (GLfloat)texture->getSamplerState().wrapR; + break; + case GL_TEXTURE_IMMUTABLE_FORMAT: + // Exposed to ES2.0 through EXT_texture_storage, no client version validation. + *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE); + break; + case GL_TEXTURE_IMMUTABLE_LEVELS: + if (context->getClientVersion() < 3) { - case GL_TEXTURE_MAG_FILTER: - *params = (GLfloat)texture->getMagFilter(); - break; - case GL_TEXTURE_MIN_FILTER: - *params = (GLfloat)texture->getMinFilter(); - break; - case GL_TEXTURE_WRAP_S: - *params = (GLfloat)texture->getWrapS(); - break; - case GL_TEXTURE_WRAP_T: - *params = (GLfloat)texture->getWrapT(); - break; - case GL_TEXTURE_IMMUTABLE_FORMAT_EXT: - *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE); - break; - case GL_TEXTURE_USAGE_ANGLE: - *params = (GLfloat)texture->getUsage(); - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if (!context->supportsTextureFilterAnisotropy()) - { - return gl::error(GL_INVALID_ENUM); - } - *params = (GLfloat)texture->getMaxAnisotropy(); - break; - default: return gl::error(GL_INVALID_ENUM); } - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } -} - -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); - - try - { - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - gl::Texture *texture; - - switch (target) + *params = (GLfloat)texture->immutableLevelCount(); + break; + case GL_TEXTURE_USAGE_ANGLE: + *params = (GLfloat)texture->getUsage(); + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (!context->getExtensions().textureFilterAnisotropic) { - case GL_TEXTURE_2D: - texture = context->getTexture2D(); - break; - case GL_TEXTURE_CUBE_MAP: - texture = context->getTextureCubeMap(); - break; - default: return gl::error(GL_INVALID_ENUM); } - - switch (pname) + *params = (GLfloat)texture->getSamplerState().maxAnisotropy; + break; + case GL_TEXTURE_SWIZZLE_R: + if (context->getClientVersion() < 3) { - case GL_TEXTURE_MAG_FILTER: - *params = texture->getMagFilter(); - break; - case GL_TEXTURE_MIN_FILTER: - *params = texture->getMinFilter(); - break; - case GL_TEXTURE_WRAP_S: - *params = texture->getWrapS(); - break; - case GL_TEXTURE_WRAP_T: - *params = texture->getWrapT(); - break; - case GL_TEXTURE_IMMUTABLE_FORMAT_EXT: - *params = texture->isImmutable() ? GL_TRUE : GL_FALSE; - break; - case GL_TEXTURE_USAGE_ANGLE: - *params = texture->getUsage(); - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if (!context->supportsTextureFilterAnisotropy()) - { - return gl::error(GL_INVALID_ENUM); - } - *params = (GLint)texture->getMaxAnisotropy(); - break; - default: return gl::error(GL_INVALID_ENUM); } + *params = (GLfloat)texture->getSamplerState().swizzleRed; + break; + case GL_TEXTURE_SWIZZLE_G: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = (GLfloat)texture->getSamplerState().swizzleGreen; + break; + case GL_TEXTURE_SWIZZLE_B: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = (GLfloat)texture->getSamplerState().swizzleBlue; + break; + case GL_TEXTURE_SWIZZLE_A: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = (GLfloat)texture->getSamplerState().swizzleAlpha; + break; + case GL_TEXTURE_BASE_LEVEL: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = (GLfloat)texture->getSamplerState().baseLevel; + break; + case GL_TEXTURE_MAX_LEVEL: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = (GLfloat)texture->getSamplerState().maxLevel; + break; + case GL_TEXTURE_MIN_LOD: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = texture->getSamplerState().minLod; + break; + case GL_TEXTURE_MAX_LOD: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = texture->getSamplerState().maxLod; + break; + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } -void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params) +void __stdcall glGetTexParameteriv(GLenum target, GLenum pname, GLint* params) { - EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)", - program, location, bufSize, params); + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (bufSize < 0) + gl::Texture *texture = context->getTargetTexture(target); + + if (!texture) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_ENUM); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + switch (pname) { - if (program == 0) + case GL_TEXTURE_MAG_FILTER: + *params = texture->getSamplerState().magFilter; + break; + case GL_TEXTURE_MIN_FILTER: + *params = texture->getSamplerState().minFilter; + break; + case GL_TEXTURE_WRAP_S: + *params = texture->getSamplerState().wrapS; + break; + case GL_TEXTURE_WRAP_T: + *params = texture->getSamplerState().wrapT; + break; + case GL_TEXTURE_WRAP_R: + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_ENUM); } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) + *params = texture->getSamplerState().wrapR; + break; + case GL_TEXTURE_IMMUTABLE_FORMAT: + // Exposed to ES2.0 through EXT_texture_storage, no client version validation. + *params = texture->isImmutable() ? GL_TRUE : GL_FALSE; + break; + case GL_TEXTURE_IMMUTABLE_LEVELS: + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_ENUM); } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) + *params = texture->immutableLevelCount(); + break; + case GL_TEXTURE_USAGE_ANGLE: + *params = texture->getUsage(); + break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (!context->getExtensions().textureFilterAnisotropic) { - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_ENUM); } - - if (!programBinary->getUniformfv(location, &bufSize, params)) + *params = (GLint)texture->getSamplerState().maxAnisotropy; + break; + case GL_TEXTURE_SWIZZLE_R: + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_ENUM); + } + *params = texture->getSamplerState().swizzleRed; + break; + case GL_TEXTURE_SWIZZLE_G: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = texture->getSamplerState().swizzleGreen; + break; + case GL_TEXTURE_SWIZZLE_B: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = texture->getSamplerState().swizzleBlue; + break; + case GL_TEXTURE_SWIZZLE_A: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = texture->getSamplerState().swizzleAlpha; + break; + case GL_TEXTURE_BASE_LEVEL: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = texture->getSamplerState().baseLevel; + break; + case GL_TEXTURE_MAX_LEVEL: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = texture->getSamplerState().maxLevel; + break; + case GL_TEXTURE_MIN_LOD: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); + } + *params = (GLint)texture->getSamplerState().minLod; + break; + case GL_TEXTURE_MAX_LOD: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM); } + *params = (GLint)texture->getSamplerState().maxLod; + break; + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) +} + +void __stdcall glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params) +{ + EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)", + program, location, bufSize, params); + + if (bufSize < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (program == 0) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Program *programObject = context->getProgram(program); + + if (!programObject || !programObject->isLinked()) + { + return gl::error(GL_INVALID_OPERATION); + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (!programBinary->getUniformfv(location, &bufSize, params)) + { + return gl::error(GL_INVALID_OPERATION); + } } } @@ -4033,169 +3038,141 @@ void __stdcall glGetUniformfv(GLuint program, GLint location, GLfloat* params) { EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (program == 0) { - if (program == 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Program *programObject = context->getProgram(program); + gl::Program *programObject = context->getProgram(program); - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!programObject || !programObject->isLinked()) + { + return gl::error(GL_INVALID_OPERATION); + } - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + return gl::error(GL_INVALID_OPERATION); + } - if (!programBinary->getUniformfv(location, NULL, params)) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!programBinary->getUniformfv(location, NULL, params)) + { + return gl::error(GL_INVALID_OPERATION); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params) { - EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)", + EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)", program, location, bufSize, params); - try + if (bufSize < 0) { - if (bufSize < 0) + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (program == 0) { return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject || !programObject->isLinked()) { - if (program == 0) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION); + } - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + return gl::error(GL_INVALID_OPERATION); + } - if (!programBinary->getUniformiv(location, &bufSize, params)) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!programBinary->getUniformiv(location, &bufSize, params)) + { + return gl::error(GL_INVALID_OPERATION); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glGetUniformiv(GLuint program, GLint location, GLint* params) { EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (program == 0) { - if (program == 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Program *programObject = context->getProgram(program); + gl::Program *programObject = context->getProgram(program); - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!programObject || !programObject->isLinked()) + { + return gl::error(GL_INVALID_OPERATION); + } - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + return gl::error(GL_INVALID_OPERATION); + } - if (!programBinary->getUniformiv(location, NULL, params)) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!programBinary->getUniformiv(location, NULL, params)) + { + return gl::error(GL_INVALID_OPERATION); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } int __stdcall glGetUniformLocation(GLuint program, const GLchar* name) { EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name); - try + gl::Context *context = gl::getNonLostContext(); + + if (strstr(name, "gl_") == name) { - gl::Context *context = gl::getNonLostContext(); + return -1; + } - if (strstr(name, "gl_") == name) - { - return -1; - } + if (context) + { + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION, -1); - } - else - { - return gl::error(GL_INVALID_VALUE, -1); - } + return gl::error(GL_INVALID_OPERATION, -1); } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (!programObject->isLinked() || !programBinary) + else { - return gl::error(GL_INVALID_OPERATION, -1); + return gl::error(GL_INVALID_VALUE, -1); } + } - return programBinary->getUniformLocation(name); + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programObject->isLinked() || !programBinary) + { + return gl::error(GL_INVALID_OPERATION, -1); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, -1); + + return programBinary->getUniformLocation(name); } return -1; @@ -4205,112 +3182,69 @@ 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); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } - if (context) + const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); + if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion())) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + return; + } + + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) { - return gl::error(GL_INVALID_VALUE); + params[i] = currentValueData.FloatValues[i]; } + } + else + { + *params = gl::QuerySingleVertexAttributeParameter(attribState, pname); + } + } +} - const gl::VertexAttribute &attribState = context->getVertexAttribState(index); +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); - switch (pname) - { - case GL_VERTEX_ATTRIB_ARRAY_ENABLED: - *params = (GLfloat)(attribState.mArrayEnabled ? GL_TRUE : GL_FALSE); - break; - case GL_VERTEX_ATTRIB_ARRAY_SIZE: - *params = (GLfloat)attribState.mSize; - break; - case GL_VERTEX_ATTRIB_ARRAY_STRIDE: - *params = (GLfloat)attribState.mStride; - break; - case GL_VERTEX_ATTRIB_ARRAY_TYPE: - *params = (GLfloat)attribState.mType; - break; - case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: - *params = (GLfloat)(attribState.mNormalized ? GL_TRUE : GL_FALSE); - break; - case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: - *params = (GLfloat)attribState.mBoundBuffer.id(); - break; - case GL_CURRENT_VERTEX_ATTRIB: - for (int i = 0; i < 4; ++i) - { - params[i] = attribState.mCurrentValue[i]; - } - break; - case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: - *params = (GLfloat)attribState.mDivisor; - break; - default: return gl::error(GL_INVALID_ENUM); - } - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } -} - -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(); - try + if (context) { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (index >= gl::MAX_VERTEX_ATTRIBS) { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - const gl::VertexAttribute &attribState = context->getVertexAttribState(index); + const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); - switch (pname) + if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion())) + { + return; + } + + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) { - case GL_VERTEX_ATTRIB_ARRAY_ENABLED: - *params = (attribState.mArrayEnabled ? GL_TRUE : GL_FALSE); - break; - case GL_VERTEX_ATTRIB_ARRAY_SIZE: - *params = attribState.mSize; - break; - case GL_VERTEX_ATTRIB_ARRAY_STRIDE: - *params = attribState.mStride; - break; - case GL_VERTEX_ATTRIB_ARRAY_TYPE: - *params = attribState.mType; - break; - case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: - *params = (attribState.mNormalized ? GL_TRUE : GL_FALSE); - break; - case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: - *params = attribState.mBoundBuffer.id(); - break; - case GL_CURRENT_VERTEX_ATTRIB: - for (int i = 0; i < 4; ++i) - { - float currentValue = attribState.mCurrentValue[i]; - params[i] = (GLint)(currentValue > 0.0f ? floor(currentValue + 0.5f) : ceil(currentValue - 0.5f)); - } - break; - case GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE: - *params = (GLint)attribState.mDivisor; - break; - default: return gl::error(GL_INVALID_ENUM); + float currentValue = currentValueData.FloatValues[i]; + params[i] = gl::iround(currentValue); } } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + else + { + *params = gl::QuerySingleVertexAttributeParameter(attribState, pname); + } } } @@ -4318,28 +3252,21 @@ 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); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (index >= gl::MAX_VERTEX_ATTRIBS) { - if (index >= gl::MAX_VERTEX_ATTRIBS) - { - return gl::error(GL_INVALID_VALUE); - } - - if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) - { - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_VALUE); + } - *pointer = const_cast(context->getVertexAttribPointer(index)); + if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER) + { + return gl::error(GL_INVALID_ENUM); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + *pointer = const_cast(context->getState().getVertexAttribPointer(index)); } } @@ -4347,34 +3274,27 @@ void __stdcall glHint(GLenum target, GLenum mode) { EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode); - try + switch (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) - { - case GL_GENERATE_MIPMAP_HINT: - if (context) context->setGenerateMipmapHint(mode); - break; - case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: - if (context) context->setFragmentShaderDerivativeHint(mode); - break; - default: - return gl::error(GL_INVALID_ENUM); - } + case GL_FASTEST: + case GL_NICEST: + case GL_DONT_CARE: + break; + default: + return gl::error(GL_INVALID_ENUM); } - catch(std::bad_alloc&) + + gl::Context *context = gl::getNonLostContext(); + switch (target) { - return gl::error(GL_OUT_OF_MEMORY); + 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); } } @@ -4382,24 +3302,17 @@ GLboolean __stdcall glIsBuffer(GLuint buffer) { EVENT("(GLuint buffer = %d)", buffer); - try + gl::Context *context = gl::getNonLostContext(); + + if (context && buffer) { - gl::Context *context = gl::getNonLostContext(); + gl::Buffer *bufferObject = context->getBuffer(buffer); - if (context && buffer) + if (bufferObject) { - gl::Buffer *bufferObject = context->getBuffer(buffer); - - if (bufferObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4408,31 +3321,16 @@ GLboolean __stdcall glIsEnabled(GLenum cap) { EVENT("(GLenum cap = 0x%X)", cap); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!ValidCap(context, cap)) { - switch (cap) - { - case GL_CULL_FACE: return context->isCullFaceEnabled(); - case GL_POLYGON_OFFSET_FILL: return context->isPolygonOffsetFillEnabled(); - case GL_SAMPLE_ALPHA_TO_COVERAGE: return context->isSampleAlphaToCoverageEnabled(); - case GL_SAMPLE_COVERAGE: return context->isSampleCoverageEnabled(); - case GL_SCISSOR_TEST: return context->isScissorTestEnabled(); - case GL_STENCIL_TEST: return context->isStencilTestEnabled(); - case GL_DEPTH_TEST: return context->isDepthTestEnabled(); - case GL_BLEND: return context->isBlendEnabled(); - case GL_DITHER: return context->isDitherEnabled(); - default: - return gl::error(GL_INVALID_ENUM, false); - } + return gl::error(GL_INVALID_ENUM, false); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, false); + + return context->getState().getEnableFeature(cap); } return false; @@ -4442,25 +3340,18 @@ GLboolean __stdcall glIsFenceNV(GLuint fence) { EVENT("(GLuint fence = %d)", fence); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::FenceNV *fenceObject = context->getFenceNV(fence); - if (context) + if (fenceObject == NULL) { - gl::Fence *fenceObject = context->getFence(fence); - - if (fenceObject == NULL) - { - return GL_FALSE; - } - - return fenceObject->isFence(); + return GL_FALSE; } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); + + return fenceObject->isFence(); } return GL_FALSE; @@ -4470,24 +3361,17 @@ GLboolean __stdcall glIsFramebuffer(GLuint framebuffer) { EVENT("(GLuint framebuffer = %d)", framebuffer); - try + gl::Context *context = gl::getNonLostContext(); + + if (context && framebuffer) { - gl::Context *context = gl::getNonLostContext(); + gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer); - if (context && framebuffer) + if (framebufferObject) { - gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer); - - if (framebufferObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4496,24 +3380,17 @@ GLboolean __stdcall glIsProgram(GLuint program) { EVENT("(GLuint program = %d)", program); - try + gl::Context *context = gl::getNonLostContext(); + + if (context && program) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context && program) + if (programObject) { - gl::Program *programObject = context->getProgram(program); - - if (programObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4522,28 +3399,11 @@ GLboolean __stdcall glIsQueryEXT(GLuint id) { EVENT("(GLuint id = %d)", id); - try - { - if (id == 0) - { - return GL_FALSE; - } - - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - gl::Query *queryObject = context->getQuery(id, false, GL_NONE); + gl::Context *context = gl::getNonLostContext(); - if (queryObject) - { - return GL_TRUE; - } - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); + return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; } return GL_FALSE; @@ -4553,24 +3413,17 @@ GLboolean __stdcall glIsRenderbuffer(GLuint renderbuffer) { EVENT("(GLuint renderbuffer = %d)", renderbuffer); - try + gl::Context *context = gl::getNonLostContext(); + + if (context && renderbuffer) { - gl::Context *context = gl::getNonLostContext(); + gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); - if (context && renderbuffer) + if (renderbufferObject) { - gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer); - - if (renderbufferObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4579,24 +3432,17 @@ GLboolean __stdcall glIsShader(GLuint shader) { EVENT("(GLuint shader = %d)", shader); - try + gl::Context *context = gl::getNonLostContext(); + + if (context && shader) { - gl::Context *context = gl::getNonLostContext(); + gl::Shader *shaderObject = context->getShader(shader); - if (context && shader) + if (shaderObject) { - gl::Shader *shaderObject = context->getShader(shader); - - if (shaderObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4605,24 +3451,17 @@ GLboolean __stdcall glIsTexture(GLuint texture) { EVENT("(GLuint texture = %d)", texture); - try + gl::Context *context = gl::getNonLostContext(); + + if (context && texture) { - gl::Context *context = gl::getNonLostContext(); + gl::Texture *textureObject = context->getTexture(texture); - if (context && texture) + if (textureObject) { - gl::Texture *textureObject = context->getTexture(texture); - - if (textureObject) - { - return GL_TRUE; - } + return GL_TRUE; } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, GL_FALSE); - } return GL_FALSE; } @@ -4631,23 +3470,16 @@ void __stdcall glLineWidth(GLfloat width) { EVENT("(GLfloat width = %f)", width); - try + if (width <= 0.0f) { - if (width <= 0.0f) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setLineWidth(width); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setLineWidth(width); } } @@ -4655,32 +3487,25 @@ void __stdcall glLinkProgram(GLuint program) { EVENT("(GLuint program = %d)", program); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) + if (context->getShader(program)) { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); } - - context->linkProgram(program); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->linkProgram(program); } } @@ -4688,63 +3513,64 @@ void __stdcall glPixelStorei(GLenum pname, GLint param) { EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + switch (pname) { - switch (pname) + case GL_UNPACK_ALIGNMENT: + if (param != 1 && param != 2 && param != 4 && param != 8) { - case GL_UNPACK_ALIGNMENT: - if (param != 1 && param != 2 && param != 4 && param != 8) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - context->setUnpackAlignment(param); - break; + context->getState().setUnpackAlignment(param); + break; - case GL_PACK_ALIGNMENT: - if (param != 1 && param != 2 && param != 4 && param != 8) - { - return gl::error(GL_INVALID_VALUE); - } + case GL_PACK_ALIGNMENT: + if (param != 1 && param != 2 && param != 4 && param != 8) + { + return gl::error(GL_INVALID_VALUE); + } - context->setPackAlignment(param); - break; + context->getState().setPackAlignment(param); + break; - case GL_PACK_REVERSE_ROW_ORDER_ANGLE: - context->setPackReverseRowOrder(param != 0); - break; + case GL_PACK_REVERSE_ROW_ORDER_ANGLE: + context->getState().setPackReverseRowOrder(param != 0); + break; - default: + case GL_UNPACK_IMAGE_HEIGHT: + case GL_UNPACK_SKIP_IMAGES: + case GL_UNPACK_ROW_LENGTH: + case GL_UNPACK_SKIP_ROWS: + case GL_UNPACK_SKIP_PIXELS: + case GL_PACK_ROW_LENGTH: + case GL_PACK_SKIP_ROWS: + case GL_PACK_SKIP_PIXELS: + if (context->getClientVersion() < 3) + { return gl::error(GL_INVALID_ENUM); } + UNIMPLEMENTED(); + break; + + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glPolygonOffset(GLfloat factor, GLfloat units) { EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - context->setPolygonOffsetParams(factor, units); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setPolygonOffsetParams(factor, units); } } @@ -4756,36 +3582,22 @@ 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); - try + if (width < 0 || height < 0 || bufSize < 0) { - if (width < 0 || height < 0 || bufSize < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!gl::ValidateReadPixelsParameters(context, x, y, width, height, + format, type, &bufSize, data)) { - GLenum currentFormat, currentType; - - // Failure in getCurrentReadFormatType indicates that no color attachment is currently bound, - // and attempting to read back if that's the case is an error. The error will be registered - // by getCurrentReadFormat. - if (!context->getCurrentReadFormatType(¤tFormat, ¤tType)) - return; - - if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type)) - { - return gl::error(GL_INVALID_OPERATION); - } - - context->readPixels(x, y, width, height, format, type, &bufSize, data); + return; } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->readPixels(x, y, width, height, format, type, &bufSize, data); } } @@ -4796,36 +3608,22 @@ 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); - try + if (width < 0 || height < 0) { - if (width < 0 || height < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (!gl::ValidateReadPixelsParameters(context, x, y, width, height, + format, type, NULL, pixels)) { - GLenum currentFormat, currentType; - - // Failure in getCurrentReadFormatType indicates that no color attachment is currently bound, - // and attempting to read back if that's the case is an error. The error will be registered - // by getCurrentReadFormat. - if (!context->getCurrentReadFormatType(¤tFormat, ¤tType)) - return; - - if (!(currentFormat == format && currentType == type) && !validReadFormatType(format, type)) - { - return gl::error(GL_INVALID_OPERATION); - } - - context->readPixels(x, y, width, height, format, type, NULL, pixels); + return; } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->readPixels(x, y, width, height, format, type, NULL, pixels); } } @@ -4833,14 +3631,7 @@ void __stdcall glReleaseShaderCompiler(void) { EVENT("()"); - try - { - gl::Shader::releaseCompiler(); - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } + gl::Shader::releaseCompiler(); } void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) @@ -4848,64 +3639,17 @@ void __stdcall glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samp EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", target, samples, internalformat, width, height); - try - { - switch (target) - { - case GL_RENDERBUFFER: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + gl::Context *context = gl::getNonLostContext(); - if (!gl::IsColorRenderable(internalformat) && !gl::IsDepthRenderable(internalformat) && !gl::IsStencilRenderable(internalformat)) + if (context) + { + if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat, + width, height, true)) { - return gl::error(GL_INVALID_ENUM); + return; } - if (width < 0 || height < 0 || samples < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - if (width > context->getMaximumRenderbufferDimension() || - height > context->getMaximumRenderbufferDimension() || - samples > context->getMaxSupportedSamples()) - { - return gl::error(GL_INVALID_VALUE); - } - - GLuint handle = context->getRenderbufferHandle(); - if (handle == 0) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (internalformat) - { - case GL_DEPTH_COMPONENT16: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGB565: - case GL_RGB8_OES: - case GL_RGBA8_OES: - case GL_STENCIL_INDEX8: - case GL_DEPTH24_STENCIL8_OES: - case GL_BGRA8_EXT: - context->setRenderbufferStorage(width, height, internalformat, samples); - break; - default: - return gl::error(GL_INVALID_ENUM); - } - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + context->setRenderbufferStorage(width, height, internalformat, samples); } } @@ -4916,20 +3660,13 @@ void __stdcall glRenderbufferStorage(GLenum target, GLenum internalformat, GLsiz void __stdcall glSampleCoverage(GLclampf value, GLboolean invert) { - EVENT("(GLclampf value = %f, GLboolean invert = %d)", value, invert); + EVENT("(GLclampf value = %f, GLboolean invert = %u)", value, invert); - try - { - gl::Context* context = gl::getNonLostContext(); + gl::Context* context = gl::getNonLostContext(); - if (context) - { - context->setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE); } } @@ -4937,30 +3674,23 @@ void __stdcall glSetFenceNV(GLuint fence, GLenum condition) { EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition); - try + if (condition != GL_ALL_COMPLETED_NV) { - if (condition != GL_ALL_COMPLETED_NV) - { - return gl::error(GL_INVALID_ENUM); - } - - gl::Context *context = gl::getNonLostContext(); + return gl::error(GL_INVALID_ENUM); + } - if (context) - { - gl::Fence *fenceObject = context->getFence(fence); + gl::Context *context = gl::getNonLostContext(); - if (fenceObject == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } + if (context) + { + gl::FenceNV *fenceObject = context->getFenceNV(fence); - fenceObject->setFence(condition); + if (fenceObject == NULL) + { + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + fenceObject->setFence(condition); } } @@ -4968,23 +3698,16 @@ 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); - try + if (width < 0 || height < 0) { - if (width < 0 || height < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context* context = gl::getNonLostContext(); + gl::Context* context = gl::getNonLostContext(); - if (context) - { - context->setScissorParams(x, y, width, height); - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + context->getState().setScissorParams(x, y, width, height); } } @@ -4994,53 +3717,39 @@ void __stdcall glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryfor "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", n, shaders, binaryformat, binary, length); - try - { - // No binary shader formats are supported. - return gl::error(GL_INVALID_ENUM); - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } + // No binary shader formats are supported. + return gl::error(GL_INVALID_ENUM); } -void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar** string, const GLint* length) +void __stdcall glShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length) { EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)", shader, count, string, length); - try + if (count < 0) { - if (count < 0) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_VALUE); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) - { - gl::Shader *shaderObject = context->getShader(shader); + if (context) + { + gl::Shader *shaderObject = context->getShader(shader); - if (!shaderObject) + if (!shaderObject) + { + if (context->getProgram(shader)) { - if (context->getProgram(shader)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); } - - shaderObject->setSource(count, string, length); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + shaderObject->setSource(count, string, length); } } @@ -5053,52 +3762,45 @@ 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); - try + switch (face) { - switch (face) - { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + default: + return gl::error(GL_INVALID_ENUM); + } - 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); - } + 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); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { - if (face == GL_FRONT || face == GL_FRONT_AND_BACK) - { - context->setStencilParams(func, ref, mask); - } + context->getState().setStencilParams(func, ref, mask); + } - if (face == GL_BACK || face == GL_FRONT_AND_BACK) - { - context->setStencilBackParams(func, ref, mask); - } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilBackParams(func, ref, mask); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glStencilMask(GLuint mask) @@ -5110,37 +3812,30 @@ void __stdcall glStencilMaskSeparate(GLenum face, GLuint mask) { EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask); - try + switch (face) { - switch (face) - { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + default: + return gl::error(GL_INVALID_ENUM); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { - if (face == GL_FRONT || face == GL_FRONT_AND_BACK) - { - context->setStencilWritemask(mask); - } + context->getState().setStencilWritemask(mask); + } - if (face == GL_BACK || face == GL_FRONT_AND_BACK) - { - context->setStencilBackWritemask(mask); - } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilBackWritemask(mask); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } void __stdcall glStencilOp(GLenum fail, GLenum zfail, GLenum zpass) @@ -5153,109 +3848,100 @@ 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); - try + switch (face) { - switch (face) - { - case GL_FRONT: - case GL_BACK: - case GL_FRONT_AND_BACK: - break; - default: - return gl::error(GL_INVALID_ENUM); - } + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + 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; - 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; + default: + return gl::error(GL_INVALID_ENUM); + } - 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 (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 (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); - } + 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); + } - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (face == GL_FRONT || face == GL_FRONT_AND_BACK) { - if (face == GL_FRONT || face == GL_FRONT_AND_BACK) - { - context->setStencilOperations(fail, zfail, zpass); - } + context->getState().setStencilOperations(fail, zfail, zpass); + } - if (face == GL_BACK || face == GL_FRONT_AND_BACK) - { - context->setStencilBackOperations(fail, zfail, zpass); - } + if (face == GL_BACK || face == GL_FRONT_AND_BACK) + { + context->getState().setStencilBackOperations(fail, zfail, zpass); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } GLboolean __stdcall glTestFenceNV(GLuint fence) { EVENT("(GLuint fence = %d)", fence); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::FenceNV *fenceObject = context->getFenceNV(fence); - if (context) + if (fenceObject == NULL) { - gl::Fence *fenceObject = context->getFence(fence); - - if (fenceObject == NULL) - { - return gl::error(GL_INVALID_OPERATION, GL_TRUE); - } + return gl::error(GL_INVALID_OPERATION, GL_TRUE); + } - return fenceObject->testFence(); + if (fenceObject->isFence() != GL_TRUE) + { + return gl::error(GL_INVALID_OPERATION, GL_TRUE); } + + return fenceObject->testFence(); } - catch(std::bad_alloc&) - { - gl::error(GL_OUT_OF_MEMORY); - } - + return GL_TRUE; } @@ -5263,1759 +3949,4337 @@ void __stdcall glTexImage2D(GLenum target, GLint level, GLint internalformat, GL GLint border, GLenum format, GLenum type, const GLvoid* pixels) { EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, " - "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", + "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", target, level, internalformat, width, height, border, format, type, pixels); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (!validImageSize(level, width, height)) + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, internalformat, false, false, + 0, 0, width, height, border, format, type, pixels)) { - return gl::error(GL_INVALID_VALUE); + return; } - if (internalformat != GLint(format)) + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, internalformat, false, false, + 0, 0, 0, width, height, 1, border, format, type, pixels)) { - return gl::error(GL_INVALID_OPERATION); + return; } - // validate by itself (used as secondary key below) - switch (type) + switch (target) { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - case GL_UNSIGNED_SHORT: - case GL_UNSIGNED_INT: - case GL_UNSIGNED_INT_24_8_OES: - case GL_HALF_FLOAT_OES: - case GL_FLOAT: + case GL_TEXTURE_2D: + { + gl::Texture2D *texture = context->getTexture2D(); + texture->setImage(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); + } break; - default: - return gl::error(GL_INVALID_ENUM); - } - - // validate + combinations - // - invalid -> sets INVALID_ENUM - // - invalid + combination -> sets INVALID_OPERATION - switch (format) - { - case GL_ALPHA: - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - switch (type) + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: { - case GL_UNSIGNED_BYTE: - case GL_FLOAT: - case GL_HALF_FLOAT_OES: - break; - default: - return gl::error(GL_INVALID_OPERATION); + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImagePosX(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); } break; - case GL_RGB: - switch (type) + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_5_6_5: - case GL_FLOAT: - case GL_HALF_FLOAT_OES: - break; - default: - return gl::error(GL_INVALID_OPERATION); + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImageNegX(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); } break; - case GL_RGBA: - switch (type) + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: { - case GL_UNSIGNED_BYTE: - case GL_UNSIGNED_SHORT_4_4_4_4: - case GL_UNSIGNED_SHORT_5_5_5_1: - case GL_FLOAT: - case GL_HALF_FLOAT_OES: - break; - default: - return gl::error(GL_INVALID_OPERATION); + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImagePosY(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); } break; - case GL_BGRA_EXT: - switch (type) + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: { - case GL_UNSIGNED_BYTE: - break; - default: - return gl::error(GL_INVALID_OPERATION); + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImageNegY(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); } break; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - break; - case GL_DEPTH_COMPONENT: - switch (type) + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: { - case GL_UNSIGNED_SHORT: - case GL_UNSIGNED_INT: - break; - default: - return gl::error(GL_INVALID_OPERATION); + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImagePosZ(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); } break; - case GL_DEPTH_STENCIL_OES: - switch (type) + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: { - case GL_UNSIGNED_INT_24_8_OES: - break; - default: - return gl::error(GL_INVALID_OPERATION); + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->setImageNegZ(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels); } break; - default: - return gl::error(GL_INVALID_ENUM); + default: UNREACHABLE(); } + } +} + +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 (border != 0) + if (context) + { + if (!ValidateTexParamParameters(context, pname, static_cast(param))) { - return gl::error(GL_INVALID_VALUE); + return; } - gl::Context *context = gl::getNonLostContext(); + gl::Texture *texture = context->getTargetTexture(target); - if (context) + if (!texture) { - if (level > context->getMaximumTextureLevel()) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_ENUM); + } - switch (target) - { - case GL_TEXTURE_2D: - if (width > (context->getMaximumTextureDimension() >> level) || - height > (context->getMaximumTextureDimension() >> level)) - { - return gl::error(GL_INVALID_VALUE); - } - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - if (width != height) + switch (pname) + { + case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = gl::uiround(param); break; + case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = gl::uiround(param); break; + case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = gl::uiround(param); break; + case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = gl::uiround(param); break; + case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = gl::uiround(param); break; + case GL_TEXTURE_USAGE_ANGLE: texture->setUsage(gl::uiround(param)); break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min(param, context->getExtensions().maxTextureAnisotropy); break; + case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = gl::uiround(param); break; + case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = gl::uiround(param); break; + case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = gl::uiround(param); break; + case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = gl::uiround(param); break; + case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = gl::uiround(param); break; + case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = gl::uiround(param); break; + case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = gl::iround(param); break; + case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = gl::iround(param); break; + case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = param; break; + case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = param; break; + default: UNREACHABLE(); break; + } + } +} + +void __stdcall glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params) +{ + glTexParameterf(target, pname, (GLfloat)*params); +} + +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)) + { + return; + } + + gl::Texture *texture = context->getTargetTexture(target); + + if (!texture) + { + return gl::error(GL_INVALID_ENUM); + } + + switch (pname) + { + case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = (GLenum)param; break; + case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = (GLenum)param; break; + case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = (GLenum)param; break; + case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = (GLenum)param; break; + case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = (GLenum)param; break; + case GL_TEXTURE_USAGE_ANGLE: texture->setUsage((GLenum)param); break; + case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min((float)param, context->getExtensions().maxTextureAnisotropy); break; + case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = (GLenum)param; break; + case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = (GLenum)param; break; + case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = (GLenum)param; break; + case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = param; break; + case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = param; break; + case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = (GLfloat)param; break; + case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = (GLfloat)param; break; + default: UNREACHABLE(); break; + } + } +} + +void __stdcall glTexParameteriv(GLenum target, GLenum pname, const GLint* params) +{ + glTexParameteri(target, pname, *params); +} + +void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, levels, internalformat, width, height); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!context->getExtensions().textureStorage) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (context->getClientVersion() < 3 && + !ValidateES2TexStorageParameters(context, target, levels, internalformat, width, height)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) + { + return; + } + + switch (target) + { + case GL_TEXTURE_2D: + { + gl::Texture2D *texture2d = context->getTexture2D(); + texture2d->storage(levels, internalformat, width, height); + } + break; + + case GL_TEXTURE_CUBE_MAP: + { + gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); + textureCube->storage(levels, internalformat, width); + } + break; + + default: + return gl::error(GL_INVALID_ENUM); + } + } +} + +void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, " + "const GLvoid* pixels = 0x%0.8p)", + target, level, xoffset, yoffset, width, height, format, type, pixels); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3 && + !ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true, + xoffset, yoffset, width, height, 0, format, type, pixels)) + { + return; + } + + if (context->getClientVersion() >= 3 && + !ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true, + xoffset, yoffset, 0, width, height, 1, 0, format, type, pixels)) + { + return; + } + + // Zero sized uploads are valid but no-ops + if (width == 0 || height == 0) + { + return; + } + + switch (target) + { + case GL_TEXTURE_2D: + { + gl::Texture2D *texture = context->getTexture2D(); + texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels); + } + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + { + gl::TextureCubeMap *texture = context->getTextureCubeMap(); + texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels); + } + break; + + default: + UNREACHABLE(); + } + } +} + +void __stdcall glUniform1f(GLint location, GLfloat x) +{ + glUniform1fv(location, 1, &x); +} + +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)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform1fv(location, count, v); + } +} + +void __stdcall glUniform1i(GLint location, GLint x) +{ + glUniform1iv(location, 1, &x); +} + +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)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform1iv(location, count, v); + } +} + +void __stdcall glUniform2f(GLint location, GLfloat x, GLfloat y) +{ + GLfloat xy[2] = {x, y}; + + glUniform2fv(location, 1, xy); +} + +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)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform2fv(location, count, v); + } +} + +void __stdcall glUniform2i(GLint location, GLint x, GLint y) +{ + GLint xy[2] = {x, y}; + + glUniform2iv(location, 1, xy); +} + +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)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform2iv(location, count, v); + } +} + +void __stdcall glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) +{ + GLfloat xyz[3] = {x, y, z}; + + glUniform3fv(location, 1, xyz); +} + +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)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform3fv(location, count, v); + } +} + +void __stdcall glUniform3i(GLint location, GLint x, GLint y, GLint z) +{ + GLint xyz[3] = {x, y, z}; + + glUniform3iv(location, 1, xyz); +} + +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)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform3iv(location, count, v); + } +} + +void __stdcall glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + GLfloat xyzw[4] = {x, y, z, w}; + + glUniform4fv(location, 1, xyzw); +} + +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)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform4fv(location, count, v); + } +} + +void __stdcall glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) +{ + GLint xyzw[4] = {x, y, z, w}; + + glUniform4iv(location, 1, xyzw); +} + +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)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform4iv(location, count, v); + } +} + +void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix2fv(location, count, transpose, value); + } +} + +void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix3fv(location, count, transpose, value); + } +} + +void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix4fv(location, count, transpose, value); + } +} + +void __stdcall glUseProgram(GLuint program) +{ + EVENT("(GLuint program = %d)", program); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + gl::Program *programObject = context->getProgram(program); + + if (!programObject && program != 0) + { + if (context->getShader(program)) + { + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); + } + } + + if (program != 0 && !programObject->isLinked()) + { + return gl::error(GL_INVALID_OPERATION); + } + + context->useProgram(program); + } +} + +void __stdcall glValidateProgram(GLuint program) +{ + EVENT("(GLuint program = %d)", program); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + gl::Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); + } + } + + programObject->validate(); + } +} + +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) + { + GLfloat vals[4] = { x, 0, 0, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +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) + { + GLfloat vals[4] = { values[0], 0, 0, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +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) + { + GLfloat vals[4] = { x, y, 0, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +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) + { + GLfloat vals[4] = { values[0], values[1], 0, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +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); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + GLfloat vals[4] = { x, y, z, 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +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) + { + GLfloat vals[4] = { values[0], values[1], values[2], 1 }; + context->getState().setVertexAttribf(index, vals); + } +} + +void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +{ + EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w); + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + GLfloat vals[4] = { x, y, z, w }; + context->getState().setVertexAttribf(index, vals); + } +} + +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) + { + context->getState().setVertexAttribf(index, values); + } +} + +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) + { + context->setVertexAttribDivisor(index, divisor); + } +} + +void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) +{ + EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, " + "GLboolean normalized = %u, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)", + index, size, type, normalized, stride, ptr); + + 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) + { + 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) + { + return gl::error(GL_INVALID_ENUM); + } + else + { + break; + } + default: + return gl::error(GL_INVALID_ENUM); + } + + if (stride < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + 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 (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->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, + normalized == GL_TRUE, false, stride, ptr); + } +} + +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) + { + context->getState().setViewportParams(x, y, width, height); + } +} + +// OpenGL ES 3.0 functions + +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); + } + + // glReadBuffer + UNIMPLEMENTED(); + } +} + +void __stdcall glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices) +{ + EVENT("(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type = 0x%X, " + "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + // glDrawRangeElements + UNIMPLEMENTED(); + } +} + +void __stdcall glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, " + "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, " + "GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", + target, level, internalformat, width, height, depth, border, format, type, pixels); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, internalformat, false, false, + 0, 0, 0, width, height, depth, border, format, type, pixels)) + { + return; + } + + switch(target) + { + case GL_TEXTURE_3D: + { + gl::Texture3D *texture = context->getTexture3D(); + texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels); + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + gl::Texture2DArray *texture = context->getTexture2DArray(); + texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels); + } + break; + + default: + return gl::error(GL_INVALID_ENUM); + } + } +} + +void __stdcall glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, " + "GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)", + target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true, + xoffset, yoffset, zoffset, width, height, depth, 0, + format, type, pixels)) + { + return; + } + + // Zero sized uploads are valid but no-ops + if (width == 0 || height == 0 || depth == 0) + { + return; + } + + switch(target) + { + case GL_TEXTURE_3D: + { + gl::Texture3D *texture = context->getTexture3D(); + texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels); + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + gl::Texture2DArray *texture = context->getTexture2DArray(); + texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels); + } + break; + + default: + return gl::error(GL_INVALID_ENUM); + } + } +} + +void __stdcall glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", + target, level, xoffset, yoffset, zoffset, x, y, width, height); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (!ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset, yoffset, zoffset, + x, y, width, height, 0)) + { + return; + } + + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + gl::Texture *texture = NULL; + switch (target) + { + case GL_TEXTURE_3D: + texture = context->getTexture3D(); + break; + + case GL_TEXTURE_2D_ARRAY: + texture = context->getTexture2DArray(); + break; + + default: + return gl::error(GL_INVALID_ENUM); + } + + texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer); + } +} + +void __stdcall glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " + "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, " + "const GLvoid* data = 0x%0.8p)", + target, level, internalformat, width, height, depth, border, imageSize, data); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(internalformat, GL_UNSIGNED_BYTE, width, height)) + { + return gl::error(GL_INVALID_VALUE); + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, internalformat, true, false, + 0, 0, 0, width, height, depth, border, GL_NONE, GL_NONE, data)) + { + return; + } + + switch(target) + { + case GL_TEXTURE_3D: + { + gl::Texture3D *texture = context->getTexture3D(); + texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data); + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + gl::Texture2DArray *texture = context->getTexture2DArray(); + texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, data); + } + break; + + default: + return gl::error(GL_INVALID_ENUM); + } + } +} + +void __stdcall glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data) +{ + EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " + "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, " + "GLenum format = 0x%X, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)", + target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (imageSize < 0 || imageSize != (GLsizei)gl::GetBlockSize(format, GL_UNSIGNED_BYTE, width, height)) + { + return gl::error(GL_INVALID_VALUE); + } + + if (!data) + { + return gl::error(GL_INVALID_VALUE); + } + + // validateES3TexImageFormat sets the error code if there is an error + if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true, + 0, 0, 0, width, height, depth, 0, GL_NONE, GL_NONE, data)) + { + return; + } + + // Zero sized uploads are valid but no-ops + if (width == 0 || height == 0) + { + return; + } + + switch(target) + { + case GL_TEXTURE_3D: + { + gl::Texture3D *texture = context->getTexture3D(); + texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, + format, imageSize, data); + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + gl::Texture2DArray *texture = context->getTexture2DArray(); + texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth, + format, imageSize, data); + } + break; + + default: + return gl::error(GL_INVALID_ENUM); + } + } +} + +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); + } + + if (n < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + for (GLsizei i = 0; i < n; i++) + { + ids[i] = context->createQuery(); + } + } +} + +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); + } + + if (n < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + for (GLsizei i = 0; i < n; i++) + { + context->deleteQuery(ids[i]); + } + } +} + +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); + } + + return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE; + } + + return GL_FALSE; +} + +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); + } + + if (!ValidateBeginQuery(context, target, id)) + { + return; + } + context->beginQuery(target, id); + } +} + +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); + } + + if (!ValidateEndQuery(context, target)) + { + return; + } + + context->endQuery(target); + } +} + +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); + } + + if (!ValidQueryType(context, target)) + { + return gl::error(GL_INVALID_ENUM); + } + + switch (pname) + { + case GL_CURRENT_QUERY: + params[0] = static_cast(context->getState().getActiveQueryId(target)); + break; + + default: + return gl::error(GL_INVALID_ENUM); + } + } +} + +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); + } + + gl::Query *queryObject = context->getQuery(id, false, GL_NONE); + + if (!queryObject) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (context->getState().getActiveQueryId(queryObject->getType()) == id) + { + return gl::error(GL_INVALID_OPERATION); + } + + switch(pname) + { + case GL_QUERY_RESULT: + params[0] = queryObject->getResult(); + break; + case GL_QUERY_RESULT_AVAILABLE: + params[0] = queryObject->isResultAvailable(); + break; + default: + return gl::error(GL_INVALID_ENUM); + } + } +} + +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); + } + + return glUnmapBufferOES(target); + } + + return GL_FALSE; +} + +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); + } + + glGetBufferPointervOES(target, pname, 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); + } + + glDrawBuffersEXT(n, bufs); + } +} + +void __stdcall glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix2x3fv(location, count, transpose, value); + } +} + +void __stdcall glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix3x2fv(location, count, transpose, value); + } +} + +void __stdcall glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix2x4fv(location, count, transpose, value); + } +} + +void __stdcall glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix4x2fv(location, count, transpose, value); + } +} + +void __stdcall glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix3x4fv(location, count, transpose, value); + } +} + +void __stdcall glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)", + location, count, transpose, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniformMatrix4x3fv(location, count, transpose, value); + } +} + +void __stdcall glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) +{ + EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = %d, " + "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum filter = 0x%X)", + srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter); + + gl::Context *context = gl::getNonLostContext(); + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter, + false)) + { + return; + } + + context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, + mask, filter); + } +} + +void __stdcall glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height) +{ + EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, samples, internalformat, width, height); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat, + width, height, false)) + { + return; + } + + context->setRenderbufferStorage(width, height, internalformat, samples); + } +} + +void __stdcall glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer) +{ + EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, GLint layer = %d)", + target, attachment, texture, level, layer); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateFramebufferTextureLayer(context, target, attachment, texture, + level, layer)) + { + return; + } + + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + ASSERT(framebuffer); + + gl::Texture *textureObject = context->getTexture(texture); + GLenum textarget = textureObject ? textureObject->getTarget() : GL_NONE; + + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + framebuffer->setColorbuffer(colorAttachment, textarget, texture, level, layer); + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: framebuffer->setDepthbuffer(textarget, texture, level, layer); break; + case GL_STENCIL_ATTACHMENT: framebuffer->setStencilbuffer(textarget, texture, level, layer); break; + case GL_DEPTH_STENCIL_ATTACHMENT: framebuffer->setDepthStencilBuffer(textarget, texture, level, layer); break; + } + } + } +} + +GLvoid* __stdcall glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) +{ + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)", + target, offset, length, access); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); + } + + return glMapBufferRangeEXT(target, offset, length, access); + } + + return NULL; +} + +void __stdcall glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) +{ + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + glFlushMappedBufferRangeEXT(target, offset, length); + } +} + +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); + } + + gl::VertexArray *vao = context->getVertexArray(array); + + if (!vao) + { + // The default VAO should always exist + ASSERT(array != 0); + return gl::error(GL_INVALID_OPERATION); + } + + context->bindVertexArray(array); + } +} + +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); + } + + if (n < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) + { + if (arrays[arrayIndex] != 0) + { + context->deleteVertexArray(arrays[arrayIndex]); + } + } + } +} + +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); + } + + if (n < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + for (int arrayIndex = 0; arrayIndex < n; arrayIndex++) + { + arrays[arrayIndex] = context->createVertexArray(); + } + } +} + +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); + } + + if (array == 0) + { + return GL_FALSE; + } + + gl::VertexArray *vao = context->getVertexArray(array); + + return (vao != NULL ? GL_TRUE : GL_FALSE); + } + + return GL_FALSE; +} + +void __stdcall glGetIntegeri_v(GLenum target, GLuint index, GLint* data) +{ + EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)", + target, index, data); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + 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); + 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); + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + if (!(context->getIndexedIntegerv(target, index, data))) + { + GLenum nativeType; + unsigned int numParams = 0; + if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) + return gl::error(GL_INVALID_ENUM); + + if (numParams == 0) + return; // it is known that pname is valid, but there are no parameters to return + + if (nativeType == GL_INT_64_ANGLEX) + { + GLint64 minIntValue = static_cast(std::numeric_limits::min()); + GLint64 maxIntValue = static_cast(std::numeric_limits::max()); + GLint64 *int64Params = new GLint64[numParams]; + + context->getIndexedInteger64v(target, index, int64Params); + + for (unsigned int i = 0; i < numParams; ++i) { - return gl::error(GL_INVALID_VALUE); + GLint64 clampedValue = std::max(std::min(int64Params[i], maxIntValue), minIntValue); + data[i] = static_cast(clampedValue); } - if (width > (context->getMaximumCubeTextureDimension() >> level) || - height > (context->getMaximumCubeTextureDimension() >> level)) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: - return gl::error(GL_INVALID_ENUM); + delete [] int64Params; + } + else + { + UNREACHABLE(); + } + } + } +} + +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); + } + + switch (primitiveMode) + { + case GL_TRIANGLES: + case GL_LINES: + case GL_POINTS: + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + if (transformFeedback->isStarted()) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (transformFeedback->isPaused()) + { + transformFeedback->resume(); + } + else + { + transformFeedback->start(primitiveMode); + } + } +} + +void __stdcall glEndTransformFeedback(void) +{ + EVENT("(void)"); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); + + if (!transformFeedback->isStarted()) + { + return gl::error(GL_INVALID_OPERATION); + } + + transformFeedback->stop(); + } +} + +void __stdcall glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size) +{ + EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizeiptr size = %d)", + target, index, buffer, offset, size); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + if (index >= context->getMaxTransformFeedbackBufferBindings()) + { + return gl::error(GL_INVALID_VALUE); + } + break; + + case GL_UNIFORM_BUFFER: + if (index >= context->getMaximumCombinedUniformBufferBindings()) + { + return gl::error(GL_INVALID_VALUE); + } + break; + + default: + return gl::error(GL_INVALID_ENUM); + } + + if (buffer != 0 && size <= 0) + { + return gl::error(GL_INVALID_VALUE); + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + + // size and offset must be a multiple of 4 + if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0)) + { + return gl::error(GL_INVALID_VALUE); + } + + context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size); + context->bindGenericTransformFeedbackBuffer(buffer); + break; + + case GL_UNIFORM_BUFFER: + + // it is an error to bind an offset not a multiple of the alignment + if (buffer != 0 && (offset % context->getUniformBufferOffsetAlignment()) != 0) + { + return gl::error(GL_INVALID_VALUE); + } + + context->bindIndexedUniformBuffer(buffer, index, offset, size); + context->bindGenericUniformBuffer(buffer); + break; + + default: + UNREACHABLE(); + } + } +} + +void __stdcall glBindBufferBase(GLenum target, GLuint index, GLuint buffer) +{ + EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)", + target, index, buffer); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + if (index >= context->getMaxTransformFeedbackBufferBindings()) + { + return gl::error(GL_INVALID_VALUE); + } + break; + + case GL_UNIFORM_BUFFER: + if (index >= context->getMaximumCombinedUniformBufferBindings()) + { + return gl::error(GL_INVALID_VALUE); + } + break; + + default: + return gl::error(GL_INVALID_ENUM); + } + + switch (target) + { + case GL_TRANSFORM_FEEDBACK_BUFFER: + context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0); + context->bindGenericTransformFeedbackBuffer(buffer); + break; + + case GL_UNIFORM_BUFFER: + context->bindIndexedUniformBuffer(buffer, index, 0, 0); + context->bindGenericUniformBuffer(buffer); + break; + + default: + UNREACHABLE(); + } + } +} + +void __stdcall glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode) +{ + EVENT("(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum bufferMode = 0x%X)", + program, count, varyings, bufferMode); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (count < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + switch (bufferMode) + { + case GL_INTERLEAVED_ATTRIBS: + break; + case GL_SEPARATE_ATTRIBS: + if (static_cast(count) > context->getMaxTransformFeedbackBufferBindings()) + { + return gl::error(GL_INVALID_VALUE); + } + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + if (!gl::ValidProgram(context, program)) + { + return; + } + + gl::Program *programObject = context->getProgram(program); + ASSERT(programObject); + + programObject->setTransformFeedbackVaryings(count, varyings, bufferMode); + } +} + +void __stdcall glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name) +{ + EVENT("(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, " + "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)", + program, index, bufSize, length, size, type, name); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (bufSize < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + if (!gl::ValidProgram(context, program)) + { + return; + } + + gl::Program *programObject = context->getProgram(program); + ASSERT(programObject); + + if (index >= static_cast(programObject->getTransformFeedbackVaryingCount())) + { + return gl::error(GL_INVALID_VALUE); + } + + programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name); + } +} + +void __stdcall glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer) +{ + EVENT("(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid* pointer = 0x%0.8p)", + index, size, type, stride, pointer); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + } + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + if (size < 1 || size > 4) + { + return gl::error(GL_INVALID_VALUE); + } + + 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); + } + + if (stride < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + 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 (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->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, false, true, + stride, pointer); + } +} + +void __stdcall glGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params) +{ + EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", + index, pname, params); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); + + if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion())) + { + return; + } + + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) + { + params[i] = currentValueData.IntValues[i]; + } + } + else + { + *params = gl::QuerySingleVertexAttributeParameter(attribState, pname); + } + } +} + +void __stdcall glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params) +{ + EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)", + index, pname, params); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index); + + if (!gl::ValidateGetVertexAttribParameters(pname, context->getClientVersion())) + { + return; + } + + if (pname == GL_CURRENT_VERTEX_ATTRIB) + { + const gl::VertexAttribCurrentValueData ¤tValueData = context->getState().getVertexAttribCurrentValue(index); + for (int i = 0; i < 4; ++i) + { + params[i] = currentValueData.UnsignedIntValues[i]; + } + } + else + { + *params = gl::QuerySingleVertexAttributeParameter(attribState, pname); + } + } +} + +void __stdcall glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w) +{ + EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)", + index, x, y, z, w); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + GLint vals[4] = { x, y, z, w }; + context->getState().setVertexAttribi(index, vals); + } +} + +void __stdcall glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w) +{ + EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)", + index, x, y, z, w); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + GLuint vals[4] = { x, y, z, w }; + context->getState().setVertexAttribu(index, vals); + } +} + +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); + } + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + context->getState().setVertexAttribi(index, v); + } +} + +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); + } + + if (index >= gl::MAX_VERTEX_ATTRIBS) + { + return gl::error(GL_INVALID_VALUE); + } + + context->getState().setVertexAttribu(index, v); + } +} + +void __stdcall glGetUniformuiv(GLuint program, GLint location, GLuint* params) +{ + EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)", + program, location, params); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (program == 0) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Program *programObject = context->getProgram(program); + + if (!programObject || !programObject->isLinked()) + { + return gl::error(GL_INVALID_OPERATION); + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (!programBinary->getUniformuiv(location, NULL, params)) + { + return gl::error(GL_INVALID_OPERATION); + } + } +} + +GLint __stdcall glGetFragDataLocation(GLuint program, const GLchar *name) +{ + EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)", + program, name); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, -1); + } + + if (program == 0) + { + return gl::error(GL_INVALID_VALUE, -1); + } + + gl::Program *programObject = context->getProgram(program); + + if (!programObject || !programObject->isLinked()) + { + return gl::error(GL_INVALID_OPERATION, -1); + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + return gl::error(GL_INVALID_OPERATION, -1); + } + + return programBinary->getFragDataLocation(name); + } + + return 0; +} + +void __stdcall glUniform1ui(GLint location, GLuint v0) +{ + glUniform1uiv(location, 1, &v0); +} + +void __stdcall glUniform2ui(GLint location, GLuint v0, GLuint v1) +{ + const GLuint xy[] = { v0, v1 }; + glUniform2uiv(location, 1, xy); +} + +void __stdcall glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2) +{ + const GLuint xyz[] = { v0, v1, v2 }; + glUniform3uiv(location, 1, xyz); +} + +void __stdcall glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3) +{ + const GLuint xyzw[] = { v0, v1, v2, v3 }; + glUniform4uiv(location, 1, xyzw); +} + +void __stdcall glUniform1uiv(GLint location, GLsizei count, const GLuint* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", + location, count, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform1uiv(location, count, value); + } +} + +void __stdcall glUniform2uiv(GLint location, GLsizei count, const GLuint* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", + location, count, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform2uiv(location, count, value); + } +} + +void __stdcall glUniform3uiv(GLint location, GLsizei count, const GLuint* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)", + location, count, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform3uiv(location, count, value); + } +} + +void __stdcall glUniform4uiv(GLint location, GLsizei count, const GLuint* value) +{ + EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)", + location, count, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count)) + { + return; + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + programBinary->setUniform4uiv(location, count, value); + } +} + +void __stdcall glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value) +{ + EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)", + buffer, drawbuffer, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateClearBuffer(context)) + { + return; + } + + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + return gl::error(GL_INVALID_VALUE); + } + break; + case GL_STENCIL: + if (drawbuffer != 0) + { + return gl::error(GL_INVALID_VALUE); + } + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + context->clearBufferiv(buffer, drawbuffer, value); + } +} + +void __stdcall glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value) +{ + EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)", + buffer, drawbuffer, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateClearBuffer(context)) + { + return; + } + + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + return gl::error(GL_INVALID_VALUE); + } + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + context->clearBufferuiv(buffer, drawbuffer, value); + } +} + +void __stdcall glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value) +{ + EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)", + buffer, drawbuffer, value); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateClearBuffer(context)) + { + return; + } + + switch (buffer) + { + case GL_COLOR: + if (drawbuffer < 0 || static_cast(drawbuffer) >= context->getCaps().maxDrawBuffers) + { + return gl::error(GL_INVALID_VALUE); + } + break; + case GL_DEPTH: + if (drawbuffer != 0) + { + return gl::error(GL_INVALID_VALUE); + } + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + context->clearBufferfv(buffer, drawbuffer, value); + } +} + +void __stdcall glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) +{ + EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)", + buffer, drawbuffer, depth, stencil); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (!ValidateClearBuffer(context)) + { + return; + } + + switch (buffer) + { + case GL_DEPTH_STENCIL: + if (drawbuffer != 0) + { + return gl::error(GL_INVALID_VALUE); + } + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + context->clearBufferfi(buffer, drawbuffer, depth, stencil); + } +} + +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)); + } + + if (name != GL_EXTENSIONS) + { + return gl::error(GL_INVALID_ENUM, reinterpret_cast(NULL)); + } + + if (index >= context->getExtensionStringCount()) + { + return gl::error(GL_INVALID_VALUE, reinterpret_cast(NULL)); + } + + return reinterpret_cast(context->getExtensionString(index).c_str()); + } + + return NULL; +} + +void __stdcall glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) +{ + EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)", + readTarget, writeTarget, readOffset, writeOffset, size); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (!gl::ValidBufferTarget(context, readTarget) || !gl::ValidBufferTarget(context, readTarget)) + { + return gl::error(GL_INVALID_ENUM); + } + + gl::Buffer *readBuffer = context->getState().getTargetBuffer(readTarget); + gl::Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget); + + if (!readBuffer || !writeBuffer) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (readBuffer->isMapped() || writeBuffer->isMapped()) + { + return gl::error(GL_INVALID_OPERATION); + } + + 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); + } + + if (readBuffer == writeBuffer && abs(readOffset - writeOffset) < size) + { + return gl::error(GL_INVALID_VALUE); + } + + // 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); + } + } +} + +void __stdcall glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices) +{ + EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = 0x%0.8p, GLuint* uniformIndices = 0x%0.8p)", + program, uniformCount, uniformNames, uniformIndices); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (uniformCount < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); + } + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programObject->isLinked() || !programBinary) + { + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + uniformIndices[uniformId] = GL_INVALID_INDEX; + } + } + else + { + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + uniformIndices[uniformId] = programBinary->getUniformIndex(uniformNames[uniformId]); + } + } + } +} + +void __stdcall glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params) +{ + EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", + program, uniformCount, uniformIndices, pname, params); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (uniformCount < 0) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); } + } - switch (format) { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (context->supportsDXT1Textures()) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (context->supportsDXT3Textures()) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (context->supportsDXT5Textures()) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_DEPTH_COMPONENT: - case GL_DEPTH_STENCIL_OES: - if (!context->supportsDepthTextures()) - { - return gl::error(GL_INVALID_VALUE); - } - if (target != GL_TEXTURE_2D) - { - return gl::error(GL_INVALID_OPERATION); - } - // OES_depth_texture supports loading depth data and multiple levels, - // but ANGLE_depth_texture does not - if (pixels != NULL || level != 0) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - default: - break; + switch (pname) + { + case GL_UNIFORM_TYPE: + case GL_UNIFORM_SIZE: + case GL_UNIFORM_NAME_LENGTH: + case GL_UNIFORM_BLOCK_INDEX: + case GL_UNIFORM_OFFSET: + case GL_UNIFORM_ARRAY_STRIDE: + case GL_UNIFORM_MATRIX_STRIDE: + case GL_UNIFORM_IS_ROW_MAJOR: + break; + default: + return gl::error(GL_INVALID_ENUM); + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + + if (!programBinary && uniformCount > 0) + { + return gl::error(GL_INVALID_VALUE); + } + + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + const GLuint index = uniformIndices[uniformId]; + + if (index >= (GLuint)programBinary->getActiveUniformCount()) + { + return gl::error(GL_INVALID_VALUE); } + } + + for (int uniformId = 0; uniformId < uniformCount; uniformId++) + { + const GLuint index = uniformIndices[uniformId]; + params[uniformId] = programBinary->getActiveUniformi(index, pname); + } + } +} + +GLuint __stdcall glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName) +{ + EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, GL_INVALID_INDEX); + } - if (type == GL_FLOAT) + gl::Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) { - if (!context->supportsFloat32Textures()) - { - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_OPERATION, GL_INVALID_INDEX); } - else if (type == GL_HALF_FLOAT_OES) + else { - if (!context->supportsFloat16Textures()) - { - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_VALUE, GL_INVALID_INDEX); } + } + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + if (!programBinary) + { + return GL_INVALID_INDEX; + } + + return programBinary->getUniformBlockIndex(uniformBlockName); + } + + return 0; +} + +void __stdcall glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params) +{ + EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", + program, uniformBlockIndex, pname, params); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + gl::Program *programObject = context->getProgram(program); - if (target == GL_TEXTURE_2D) + if (!programObject) + { + if (context->getShader(program)) { - gl::Texture2D *texture = context->getTexture2D(); + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); + } + } - if (!texture) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (texture->isImmutable()) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) + { + return gl::error(GL_INVALID_VALUE); + } + + switch (pname) + { + case GL_UNIFORM_BLOCK_BINDING: + *params = static_cast(programObject->getUniformBlockBinding(uniformBlockIndex)); + break; + + case GL_UNIFORM_BLOCK_DATA_SIZE: + case GL_UNIFORM_BLOCK_NAME_LENGTH: + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS: + case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES: + case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER: + case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER: + programBinary->getActiveUniformBlockiv(uniformBlockIndex, pname, params); + break; + + default: + return gl::error(GL_INVALID_ENUM); + } + } +} + +void __stdcall glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName) +{ + EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)", + program, uniformBlockIndex, bufSize, length, uniformBlockName); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } - texture->setImage(level, width, height, format, type, context->getUnpackAlignment(), pixels); + gl::Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + return gl::error(GL_INVALID_OPERATION); } else { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); + return gl::error(GL_INVALID_VALUE); + } + } - if (!texture) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (texture->isImmutable()) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) + { + return gl::error(GL_INVALID_VALUE); + } - switch (target) - { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - texture->setImagePosX(level, width, height, format, type, context->getUnpackAlignment(), pixels); - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - texture->setImageNegX(level, width, height, format, type, context->getUnpackAlignment(), pixels); - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - texture->setImagePosY(level, width, height, format, type, context->getUnpackAlignment(), pixels); - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - texture->setImageNegY(level, width, height, format, type, context->getUnpackAlignment(), pixels); - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - texture->setImagePosZ(level, width, height, format, type, context->getUnpackAlignment(), pixels); - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - texture->setImageNegZ(level, width, height, format, type, context->getUnpackAlignment(), pixels); - break; - default: UNREACHABLE(); - } + programBinary->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName); + } +} + +void __stdcall glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) +{ + EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)", + program, uniformBlockIndex, uniformBlockBinding); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (uniformBlockBinding >= context->getMaximumCombinedUniformBufferBindings()) + { + return gl::error(GL_INVALID_VALUE); + } + + gl::Program *programObject = context->getProgram(program); + + if (!programObject) + { + if (context->getShader(program)) + { + return gl::error(GL_INVALID_OPERATION); + } + else + { + return gl::error(GL_INVALID_VALUE); } } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); + + // if never linked, there won't be any uniform blocks + if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount()) + { + return gl::error(GL_INVALID_VALUE); + } + + programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding); + } +} + +void __stdcall glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount) +{ + EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)", + mode, first, count, instanceCount); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + // glDrawArraysInstanced + UNIMPLEMENTED(); + } +} + +void __stdcall glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount) +{ + EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei instanceCount = %d)", + mode, count, type, indices, instanceCount); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + // glDrawElementsInstanced + UNIMPLEMENTED(); + } +} + +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)); + } + + if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE) + { + return gl::error(GL_INVALID_ENUM, reinterpret_cast(0)); + } + + if (flags != 0) + { + return gl::error(GL_INVALID_VALUE, reinterpret_cast(0)); + } + + return context->createFenceSync(condition); + } + + return NULL; +} + +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); + } + + return (context->getFenceSync(sync) != NULL); + } + + return GL_FALSE; +} + +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); + } + + if (sync != static_cast(0) && !context->getFenceSync(sync)) + { + return gl::error(GL_INVALID_VALUE); + } + + context->deleteFenceSync(sync); } } -void __stdcall glTexParameterf(GLenum target, GLenum pname, GLfloat param) +GLenum __stdcall glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param); + EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", + sync, flags, timeout); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, GL_WAIT_FAILED); + } - if (context) + if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0) { - gl::Texture *texture; + return gl::error(GL_INVALID_VALUE, GL_WAIT_FAILED); + } - switch (target) - { - case GL_TEXTURE_2D: - texture = context->getTexture2D(); - break; - case GL_TEXTURE_CUBE_MAP: - texture = context->getTextureCubeMap(); - break; - default: - return gl::error(GL_INVALID_ENUM); - } + gl::FenceSync *fenceSync = context->getFenceSync(sync); - switch (pname) - { - case GL_TEXTURE_WRAP_S: - if (!texture->setWrapS((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_WRAP_T: - if (!texture->setWrapT((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MIN_FILTER: - if (!texture->setMinFilter((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MAG_FILTER: - if (!texture->setMagFilter((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_USAGE_ANGLE: - if (!texture->setUsage((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if (!context->supportsTextureFilterAnisotropy()) - { - return gl::error(GL_INVALID_ENUM); - } - if (!texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy())) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } + if (!fenceSync) + { + return gl::error(GL_INVALID_VALUE, GL_WAIT_FAILED); } + + return fenceSync->clientWait(flags, timeout); } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } -} -void __stdcall glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params) -{ - glTexParameterf(target, pname, (GLfloat)*params); + return GL_FALSE; } -void __stdcall glTexParameteri(GLenum target, GLenum pname, GLint param) +void __stdcall glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout) { - EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param); + EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)", + sync, flags, timeout); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } - if (context) + if (flags != 0) { - gl::Texture *texture; + return gl::error(GL_INVALID_VALUE); + } - switch (target) - { - case GL_TEXTURE_2D: - texture = context->getTexture2D(); - break; - case GL_TEXTURE_CUBE_MAP: - texture = context->getTextureCubeMap(); - break; - default: - return gl::error(GL_INVALID_ENUM); - } + if (timeout != GL_TIMEOUT_IGNORED) + { + return gl::error(GL_INVALID_VALUE); + } - switch (pname) - { - case GL_TEXTURE_WRAP_S: - if (!texture->setWrapS((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_WRAP_T: - if (!texture->setWrapT((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MIN_FILTER: - if (!texture->setMinFilter((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MAG_FILTER: - if (!texture->setMagFilter((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_USAGE_ANGLE: - if (!texture->setUsage((GLenum)param)) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_TEXTURE_MAX_ANISOTROPY_EXT: - if (!context->supportsTextureFilterAnisotropy()) - { - return gl::error(GL_INVALID_ENUM); - } - if (!texture->setMaxAnisotropy((float)param, context->getTextureMaxAnisotropy())) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: - return gl::error(GL_INVALID_ENUM); - } + gl::FenceSync *fenceSync = context->getFenceSync(sync); + + if (!fenceSync) + { + return gl::error(GL_INVALID_VALUE); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + fenceSync->serverWait(); } } -void __stdcall glTexParameteriv(GLenum target, GLenum pname, const GLint* params) +void __stdcall glGetInteger64v(GLenum pname, GLint64* params) { - glTexParameteri(target, pname, *params); + EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", + pname, params); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + GLenum nativeType; + unsigned int numParams = 0; + if (!ValidateStateQuery(context, pname, &nativeType, &numParams)) + { + return; + } + + if (nativeType == GL_INT_64_ANGLEX) + { + context->getInteger64v(pname, params); + } + else + { + CastStateValues(context, nativeType, pname, numParams, params); + } + } } -void __stdcall glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +void __stdcall glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values) { - EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", - target, levels, internalformat, width, height); + EVENT("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLint* values = 0x%0.8p)", + sync, pname, bufSize, length, values); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (target != GL_TEXTURE_2D && target != GL_TEXTURE_CUBE_MAP) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_OPERATION); } - if (width < 1 || height < 1 || levels < 1) + if (bufSize < 0) { return gl::error(GL_INVALID_VALUE); } - if (target == GL_TEXTURE_CUBE_MAP && width != height) + gl::FenceSync *fenceSync = context->getFenceSync(sync); + + if (!fenceSync) { return gl::error(GL_INVALID_VALUE); } - if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1) + switch (pname) { - return gl::error(GL_INVALID_OPERATION); + case GL_OBJECT_TYPE: values[0] = static_cast(GL_SYNC_FENCE); break; + case GL_SYNC_STATUS: values[0] = static_cast(fenceSync->getStatus()); break; + case GL_SYNC_CONDITION: values[0] = static_cast(fenceSync->getCondition()); break; + case GL_SYNC_FLAGS: values[0] = 0; break; + + default: + return gl::error(GL_INVALID_ENUM); } + } +} - GLenum format = gl::ExtractFormat(internalformat); - GLenum type = gl::ExtractType(internalformat); +void __stdcall glGetInteger64i_v(GLenum target, GLuint index, GLint64* data) +{ + EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)", + target, index, data); + + gl::Context *context = gl::getNonLostContext(); - if (format == GL_NONE || type == GL_NONE) + if (context) + { + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); + 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); + 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); + break; + default: + return gl::error(GL_INVALID_ENUM); + } - if (context) + if (!(context->getIndexedInteger64v(target, index, data))) { - switch (target) - { - case GL_TEXTURE_2D: - if (width > context->getMaximumTextureDimension() || - height > context->getMaximumTextureDimension()) - { - return gl::error(GL_INVALID_VALUE); - } - break; - case GL_TEXTURE_CUBE_MAP: - if (width > context->getMaximumCubeTextureDimension() || - height > context->getMaximumCubeTextureDimension()) - { - return gl::error(GL_INVALID_VALUE); - } - break; - default: + GLenum nativeType; + unsigned int numParams = 0; + if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams)) return gl::error(GL_INVALID_ENUM); - } - if (levels != 1 && !context->supportsNonPower2Texture()) + if (numParams == 0) + return; // it is known that pname is valid, but there are no parameters to return + + if (nativeType == GL_INT) { - if (!gl::isPow2(width) || !gl::isPow2(height)) + GLint *intParams = new GLint[numParams]; + + context->getIndexedIntegerv(target, index, intParams); + + for (unsigned int i = 0; i < numParams; ++i) { - return gl::error(GL_INVALID_OPERATION); + data[i] = static_cast(intParams[i]); } - } - switch (internalformat) + delete [] intParams; + } + else { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - if (!context->supportsDXT1Textures()) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - if (!context->supportsDXT3Textures()) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - if (!context->supportsDXT5Textures()) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_RGBA32F_EXT: - case GL_RGB32F_EXT: - case GL_ALPHA32F_EXT: - case GL_LUMINANCE32F_EXT: - case GL_LUMINANCE_ALPHA32F_EXT: - if (!context->supportsFloat32Textures()) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_RGBA16F_EXT: - case GL_RGB16F_EXT: - case GL_ALPHA16F_EXT: - case GL_LUMINANCE16F_EXT: - case GL_LUMINANCE_ALPHA16F_EXT: - if (!context->supportsFloat16Textures()) - { - return gl::error(GL_INVALID_ENUM); - } - break; - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT32_OES: - case GL_DEPTH24_STENCIL8_OES: - if (!context->supportsDepthTextures()) - { - return gl::error(GL_INVALID_ENUM); - } - if (target != GL_TEXTURE_2D) - { - return gl::error(GL_INVALID_OPERATION); - } - // ANGLE_depth_texture only supports 1-level textures - if (levels != 1) - { - return gl::error(GL_INVALID_OPERATION); - } - break; - default: - break; + UNREACHABLE(); } + } + } +} - if (target == GL_TEXTURE_2D) - { - gl::Texture2D *texture = context->getTexture2D(); +void __stdcall glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params) +{ + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)", + target, pname, params); - if (!texture || texture->id() == 0) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::Context *context = gl::getNonLostContext(); - if (texture->isImmutable()) - { - return gl::error(GL_INVALID_OPERATION); - } + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } - texture->storage(levels, internalformat, width, height); - } - else if (target == GL_TEXTURE_CUBE_MAP) - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); + if (!gl::ValidBufferTarget(context, target)) + { + return gl::error(GL_INVALID_ENUM); + } - if (!texture || texture->id() == 0) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!gl::ValidBufferParameter(context, pname)) + { + return gl::error(GL_INVALID_ENUM); + } - if (texture->isImmutable()) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::Buffer *buffer = context->getState().getTargetBuffer(target); - texture->storage(levels, internalformat, width); - } - else UNREACHABLE(); + if (!buffer) + { + // A null buffer means that "0" is bound to the requested buffer target + return gl::error(GL_INVALID_OPERATION); + } + + switch (pname) + { + case GL_BUFFER_USAGE: + *params = static_cast(buffer->getUsage()); + break; + case GL_BUFFER_SIZE: + *params = buffer->getSize(); + break; + case GL_BUFFER_ACCESS_FLAGS: + *params = static_cast(buffer->getAccessFlags()); + break; + case GL_BUFFER_MAPPED: + *params = static_cast(buffer->isMapped()); + break; + case GL_BUFFER_MAP_OFFSET: + *params = buffer->getMapOffset(); + break; + case GL_BUFFER_MAP_LENGTH: + *params = buffer->getMapLength(); + break; + default: UNREACHABLE(); break; } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } -void __stdcall glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLenum format, GLenum type, const GLvoid* pixels) +void __stdcall glGenSamplers(GLsizei count, GLuint* samplers) { - EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, " - "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, " - "const GLvoid* pixels = 0x%0.8p)", - target, level, xoffset, yoffset, width, height, format, type, pixels); + EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (!gl::IsInternalTextureTarget(target)) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_OPERATION); } - if (level < 0 || xoffset < 0 || yoffset < 0 || width < 0 || height < 0) + if (count < 0) { return gl::error(GL_INVALID_VALUE); } - if (std::numeric_limits::max() - xoffset < width || std::numeric_limits::max() - yoffset < height) + for (int i = 0; i < count; i++) { - return gl::error(GL_INVALID_VALUE); + samplers[i] = context->createSampler(); } + } +} + +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 (!checkTextureFormatType(format, type)) + if (context) + { + if (context->getClientVersion() < 3) { - return; // error is set by helper function + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); + if (count < 0) + { + return gl::error(GL_INVALID_VALUE); + } - if (context) + for (int i = 0; i < count; i++) { - if (level > context->getMaximumTextureLevel()) - { - return gl::error(GL_INVALID_VALUE); - } + context->deleteSampler(samplers[i]); + } + } +} - if (format == GL_FLOAT) - { - if (!context->supportsFloat32Textures()) - { - return gl::error(GL_INVALID_ENUM); - } - } - else if (format == GL_HALF_FLOAT_OES) - { - if (!context->supportsFloat16Textures()) - { - return gl::error(GL_INVALID_ENUM); - } - } - else if (gl::IsDepthTexture(format)) - { - if (!context->supportsDepthTextures()) - { - return gl::error(GL_INVALID_ENUM); - } - if (target != GL_TEXTURE_2D) - { - return gl::error(GL_INVALID_OPERATION); - } - // OES_depth_texture supports loading depth data, but ANGLE_depth_texture does not - return gl::error(GL_INVALID_OPERATION); - } +GLboolean __stdcall glIsSampler(GLuint sampler) +{ + EVENT("(GLuint sampler = %u)", sampler); - if (width == 0 || height == 0 || pixels == NULL) - { - return; - } + gl::Context *context = gl::getNonLostContext(); - if (target == GL_TEXTURE_2D) - { - gl::Texture2D *texture = context->getTexture2D(); - if (validateSubImageParams2D(false, width, height, xoffset, yoffset, level, format, type, texture)) - { - texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels); - } - } - else if (gl::IsCubemapTextureTarget(target)) - { - gl::TextureCubeMap *texture = context->getTextureCubeMap(); - if (validateSubImageParamsCube(false, width, height, xoffset, yoffset, target, level, format, type, texture)) - { - texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getUnpackAlignment(), pixels); - } - } - else - { - UNREACHABLE(); - } - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, GL_FALSE); + } + + return context->isSampler(sampler); } + + return GL_FALSE; } -void __stdcall glUniform1f(GLint location, GLfloat x) +void __stdcall glBindSampler(GLuint unit, GLuint sampler) { - glUniform1fv(location, 1, &x); + 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); + } + + if (sampler != 0 && !context->isSampler(sampler)) + { + return gl::error(GL_INVALID_OPERATION); + } + + if (unit >= context->getMaximumCombinedTextureImageUnits()) + { + return gl::error(GL_INVALID_VALUE); + } + + context->bindSampler(unit, sampler); + } } -void __stdcall glUniform1fv(GLint location, GLsizei count, const GLfloat* v) +void __stdcall glSamplerParameteri(GLuint sampler, GLenum pname, GLint param) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (count < 0) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (location == -1) + if (!gl::ValidateSamplerObjectParameter(pname)) { return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!gl::ValidateTexParamParameters(context, pname, param)) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + return; + } - if (!programBinary->setUniform1fv(location, count, v)) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!context->isSampler(sampler)) + { + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->samplerParameteri(sampler, pname, param); } } -void __stdcall glUniform1i(GLint location, GLint x) +void __stdcall glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param) { - glUniform1iv(location, 1, &x); + glSamplerParameteri(sampler, pname, *param); } -void __stdcall glUniform1iv(GLint location, GLsizei count, const GLint* v) +void __stdcall glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (count < 0) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (location == -1) + if (!gl::ValidateSamplerObjectParameter(pname)) { return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!gl::ValidateTexParamParameters(context, pname, static_cast(param))) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + return; + } - if (!programBinary->setUniform1iv(location, count, v)) - { - return gl::error(GL_INVALID_OPERATION); - } + if (!context->isSampler(sampler)) + { + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->samplerParameterf(sampler, pname, param); } } -void __stdcall glUniform2f(GLint location, GLfloat x, GLfloat y) +void __stdcall glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param) { - GLfloat xy[2] = {x, y}; - - glUniform2fv(location, 1, (GLfloat*)&xy); + glSamplerParameterf(sampler, pname, *param); } -void __stdcall glUniform2fv(GLint location, GLsizei count, const GLfloat* v) +void __stdcall glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname, params); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (count < 0) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - - if (location == -1) + + if (!gl::ValidateSamplerObjectParameter(pname)) { return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!context->isSampler(sampler)) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!programBinary->setUniform2fv(location, count, v)) - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + *params = context->getSamplerParameteri(sampler, pname); } } -void __stdcall glUniform2i(GLint location, GLint x, GLint y) +void __stdcall glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params) { - GLint xy[4] = {x, y}; + EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params); - glUniform2iv(location, 1, (GLint*)&xy); -} - -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(); - try + if (context) { - if (count < 0) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (location == -1) + if (!gl::ValidateSamplerObjectParameter(pname)) { return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (!context->isSampler(sampler)) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!programBinary->setUniform2iv(location, count, v)) - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + *params = context->getSamplerParameterf(sampler, pname); } } -void __stdcall glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) +void __stdcall glVertexAttribDivisor(GLuint index, GLuint divisor) { - GLfloat xyz[3] = {x, y, z}; + 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); + } - glUniform3fv(location, 1, (GLfloat*)&xyz); + context->setVertexAttribDivisor(index, divisor); + } } -void __stdcall glUniform3fv(GLint location, GLsizei count, const GLfloat* v) +void __stdcall glBindTransformFeedback(GLenum target, GLuint id) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v); + EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (count < 0) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (location == -1) + switch (target) { - return; + case GL_TRANSFORM_FEEDBACK: + { + // Cannot bind a transform feedback object if the current one is started and not paused (3.0.2 pg 85 section 2.14.1) + gl::TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback(); + if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) + { + return gl::error(GL_INVALID_OPERATION); + } + + // 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->bindTransformFeedback(id); + } + break; + + default: + return gl::error(GL_INVALID_ENUM); } + } +} + +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(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (context->getClientVersion() < 3) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION); + } - if (!programBinary->setUniform3fv(location, count, v)) - { - return gl::error(GL_INVALID_OPERATION); - } + for (int i = 0; i < n; i++) + { + context->deleteTransformFeedback(ids[i]); } } - catch(std::bad_alloc&) +} + +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) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + for (int i = 0; i < n; i++) + { + ids[i] = context->createTransformFeedback(); + } } } -void __stdcall glUniform3i(GLint location, GLint x, GLint y, GLint z) +GLboolean __stdcall glIsTransformFeedback(GLuint id) { - GLint xyz[3] = {x, y, z}; + EVENT("(GLuint id = %u)", id); + + gl::Context *context = gl::getNonLostContext(); + + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, GL_FALSE); + } + + return ((context->getTransformFeedback(id) != NULL) ? GL_TRUE : GL_FALSE); + } - glUniform3iv(location, 1, (GLint*)&xyz); + return GL_FALSE; } -void __stdcall glUniform3iv(GLint location, GLsizei count, const GLint* v) +void __stdcall glPauseTransformFeedback(void) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + EVENT("(void)"); - try - { - if (count < 0) - { - return gl::error(GL_INVALID_VALUE); - } + gl::Context *context = gl::getNonLostContext(); - if (location == -1) + if (context) + { + if (context->getClientVersion() < 3) { - return; + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); + gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); - if (context) + // Current transform feedback must be started and not paused in order to pause (3.0.2 pg 86) + if (!transformFeedback->isStarted() || transformFeedback->isPaused()) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!programBinary->setUniform3iv(location, count, v)) - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + transformFeedback->pause(); } } -void __stdcall glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w) +void __stdcall glResumeTransformFeedback(void) { - GLfloat xyzw[4] = {x, y, z, w}; + EVENT("(void)"); - glUniform4fv(location, 1, (GLfloat*)&xyzw); -} - -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(); - try + if (context) { - if (count < 0) - { - return gl::error(GL_INVALID_VALUE); - } - - if (location == -1) + if (context->getClientVersion() < 3) { - return; + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); + gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback(); + ASSERT(transformFeedback != NULL); - if (context) + // Current transform feedback must be started and paused in order to resume (3.0.2 pg 86) + if (!transformFeedback->isStarted() || !transformFeedback->isPaused()) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!programBinary->setUniform4fv(location, count, v)) - { - return gl::error(GL_INVALID_OPERATION); - } + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + transformFeedback->resume(); } } -void __stdcall glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w) +void __stdcall glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary) { - GLint xyzw[4] = {x, y, z, w}; + EVENT("(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* binaryFormat = 0x%0.8p, GLvoid* binary = 0x%0.8p)", + program, bufSize, length, binaryFormat, binary); + + gl::Context *context = gl::getNonLostContext(); - glUniform4iv(location, 1, (GLint*)&xyzw); + if (context) + { + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + // glGetProgramBinary + UNIMPLEMENTED(); + } } -void __stdcall glUniform4iv(GLint location, GLsizei count, const GLint* v) +void __stdcall glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length) { - EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v); + EVENT("(GLuint program = %u, GLenum binaryFormat = 0x%X, const GLvoid* binary = 0x%0.8p, GLsizei length = %d)", + program, binaryFormat, binary, length); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (count < 0) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (location == -1) - { - return; - } + // glProgramBinary + UNIMPLEMENTED(); + } +} - gl::Context *context = gl::getNonLostContext(); +void __stdcall glProgramParameteri(GLuint program, GLenum pname, GLint value) +{ + EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)", + program, pname, value); - if (context) - { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::Context *context = gl::getNonLostContext(); - if (!programBinary->setUniform4iv(location, count, v)) - { - return gl::error(GL_INVALID_OPERATION); - } - } - } - catch(std::bad_alloc&) + if (context) { - return gl::error(GL_OUT_OF_MEMORY); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } + + // glProgramParameteri + UNIMPLEMENTED(); } } -void __stdcall glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void __stdcall glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); + EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)", + target, numAttachments, attachments); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (count < 0 || transpose != GL_FALSE) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (location == -1) + if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) { return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!programBinary->setUniformMatrix2fv(location, count, value)) - { - return gl::error(GL_INVALID_OPERATION); - } - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + GLuint maxDimension = context->getCaps().maxRenderbufferSize; + context->invalidateFrameBuffer(target, numAttachments, attachments, 0, 0, maxDimension, maxDimension); } } -void __stdcall glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void __stdcall glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); + EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p, GLint x = %d, " + "GLint y = %d, GLsizei width = %d, GLsizei height = %d)", + target, numAttachments, attachments, x, y, width, height); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (count < 0 || transpose != GL_FALSE) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (location == -1) + if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments)) { return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!programBinary->setUniformMatrix3fv(location, count, value)) - { - return gl::error(GL_INVALID_OPERATION); - } - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + context->invalidateFrameBuffer(target, numAttachments, attachments, x, y, width, height); } } -void __stdcall glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value) +void __stdcall glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) { - EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %d, const GLfloat* value = 0x%0.8p)", - location, count, transpose, value); + EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)", + target, levels, internalformat, width, height); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (count < 0 || transpose != GL_FALSE) + if (context->getClientVersion() < 3) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - if (location == -1) + if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1)) { return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) + switch (target) { - gl::ProgramBinary *programBinary = context->getCurrentProgramBinary(); - if (!programBinary) + case GL_TEXTURE_2D: { - return gl::error(GL_INVALID_OPERATION); + gl::Texture2D *texture2d = context->getTexture2D(); + texture2d->storage(levels, internalformat, width, height); } + break; - if (!programBinary->setUniformMatrix4fv(location, count, value)) + case GL_TEXTURE_CUBE_MAP: { - return gl::error(GL_INVALID_OPERATION); + gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); + textureCube->storage(levels, internalformat, width); } + break; + + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } -void __stdcall glUseProgram(GLuint program) +void __stdcall glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) { - EVENT("(GLuint program = %d)", program); + EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, " + "GLsizei height = %d, GLsizei depth = %d)", + target, levels, internalformat, width, height, depth); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION); + } - if (context) + if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, depth)) { - gl::Program *programObject = context->getProgram(program); + return; + } - if (!programObject && program != 0) + switch (target) + { + case GL_TEXTURE_3D: { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } + gl::Texture3D *texture3d = context->getTexture3D(); + texture3d->storage(levels, internalformat, width, height, depth); } + break; - if (program != 0 && !programObject->isLinked()) + case GL_TEXTURE_2D_ARRAY: { - return gl::error(GL_INVALID_OPERATION); + gl::Texture2DArray *texture2darray = context->getTexture2DArray(); + texture2darray->storage(levels, internalformat, width, height, depth); } + break; - context->useProgram(program); + default: + UNREACHABLE(); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } -void __stdcall glValidateProgram(GLuint program) +void __stdcall glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params) { - EVENT("(GLuint program = %d)", program); + EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, " + "GLint* params = 0x%0.8p)", + target, internalformat, pname, bufSize, params); - try - { - gl::Context *context = gl::getNonLostContext(); + gl::Context *context = gl::getNonLostContext(); - if (context) + if (context) + { + if (context->getClientVersion() < 3) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject) - { - if (context->getShader(program)) - { - return gl::error(GL_INVALID_OPERATION); - } - else - { - return gl::error(GL_INVALID_VALUE); - } - } - - programObject->validate(); + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } -} - -void __stdcall glVertexAttrib1f(GLuint index, GLfloat x) -{ - EVENT("(GLuint index = %d, GLfloat x = %f)", index, x); - try - { - if (index >= gl::MAX_VERTEX_ATTRIBS) + const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); + if (!formatCaps.renderable) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_ENUM); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (target != GL_RENDERBUFFER) { - GLfloat vals[4] = { x, 0, 0, 1 }; - context->setVertexAttrib(index, vals); + return gl::error(GL_INVALID_ENUM); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } -} - -void __stdcall glVertexAttrib1fv(GLuint index, const GLfloat* values) -{ - EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); - try - { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (bufSize < 0) { return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + switch (pname) { - GLfloat vals[4] = { values[0], 0, 0, 1 }; - context->setVertexAttrib(index, vals); + case GL_NUM_SAMPLE_COUNTS: + if (bufSize != 0) + *params = context->getNumSampleCounts(internalformat); + break; + case GL_SAMPLES: + context->getSampleCounts(internalformat, bufSize, params); + break; + default: + return gl::error(GL_INVALID_ENUM); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } -void __stdcall glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y) +// Extension functions + +void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, + GLbitfield mask, GLenum filter) { - EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y); + EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, " + "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, " + "GLbitfield mask = 0x%X, GLenum filter = 0x%X)", + srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, mask, filter, + true)) { - return gl::error(GL_INVALID_VALUE); + return; } - gl::Context *context = gl::getNonLostContext(); - - if (context) - { - GLfloat vals[4] = { x, y, 0, 1 }; - context->setVertexAttrib(index, vals); - } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, + mask, filter); } } -void __stdcall glVertexAttrib2fv(GLuint index, const GLfloat* values) +void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, + GLint border, GLenum format, GLenum type, const GLvoid* pixels) { - EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, " + "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, " + "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)", + target, level, internalformat, width, height, depth, border, format, type, pixels); + + UNIMPLEMENTED(); // FIXME +} + +void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, + GLenum *binaryFormat, void *binary) +{ + EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)", + program, bufSize, length, binaryFormat, binary); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + gl::Program *programObject = context->getProgram(program); + + if (!programObject || !programObject->isLinked()) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_OPERATION); } - gl::Context *context = gl::getNonLostContext(); + gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - if (context) + if (!programBinary) { - GLfloat vals[4] = { values[0], values[1], 0, 1 }; - context->setVertexAttrib(index, vals); + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + if (!programBinary->save(binary, bufSize, length)) + { + return gl::error(GL_INVALID_OPERATION); + } + + *binaryFormat = GL_PROGRAM_BINARY_ANGLE; } } -void __stdcall glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z) +void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat, + const void *binary, GLint length) { - EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z); + EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)", + program, binaryFormat, binary, length); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (binaryFormat != GL_PROGRAM_BINARY_ANGLE) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_ENUM); } - gl::Context *context = gl::getNonLostContext(); + gl::Program *programObject = context->getProgram(program); - if (context) + if (!programObject) { - GLfloat vals[4] = { x, y, z, 1 }; - context->setVertexAttrib(index, vals); + return gl::error(GL_INVALID_OPERATION); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + context->setProgramBinary(program, binary, length); } } -void __stdcall glVertexAttrib3fv(GLuint index, const GLfloat* values) +void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs) { - EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (n < 0 || static_cast(n) > context->getCaps().maxDrawBuffers) { return gl::error(GL_INVALID_VALUE); } - gl::Context *context = gl::getNonLostContext(); + if (context->getState().getDrawFramebuffer()->id() == 0) + { + if (n != 1) + { + return gl::error(GL_INVALID_OPERATION); + } - if (context) + if (bufs[0] != GL_NONE && bufs[0] != GL_BACK) + { + return gl::error(GL_INVALID_OPERATION); + } + } + else { - GLfloat vals[4] = { values[0], values[1], values[2], 1 }; - context->setVertexAttrib(index, vals); + for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) + { + const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment; + if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment) + { + return gl::error(GL_INVALID_OPERATION); + } + } } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } -} -void __stdcall glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w) -{ - EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w); + gl::Framebuffer *framebuffer = context->getState().getDrawFramebuffer(); - try - { - if (index >= gl::MAX_VERTEX_ATTRIBS) + for (unsigned int colorAttachment = 0; colorAttachment < static_cast(n); colorAttachment++) { - return gl::error(GL_INVALID_VALUE); + framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + for (unsigned int colorAttachment = n; colorAttachment < context->getCaps().maxDrawBuffers; colorAttachment++) { - GLfloat vals[4] = { x, y, z, w }; - context->setVertexAttrib(index, vals); + framebuffer->setDrawBufferState(colorAttachment, GL_NONE); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } -void __stdcall glVertexAttrib4fv(GLuint index, const GLfloat* values) +void __stdcall glGetBufferPointervOES(GLenum target, GLenum pname, void** params) { - EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values); + EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (!gl::ValidBufferTarget(context, target)) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_ENUM); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (pname != GL_BUFFER_MAP_POINTER) { - context->setVertexAttrib(index, values); + return gl::error(GL_INVALID_ENUM); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } -} -void __stdcall glVertexAttribDivisorANGLE(GLuint index, GLuint divisor) -{ - EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor); + gl::Buffer *buffer = context->getState().getTargetBuffer(target); - try - { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (!buffer || !buffer->isMapped()) { - return gl::error(GL_INVALID_VALUE); + *params = NULL; } - - gl::Context *context = gl::getNonLostContext(); - - if (context) + else { - context->setVertexAttribDivisor(index, divisor); + *params = buffer->getMapPointer(); } } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } } -void __stdcall glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr) +void * __stdcall glMapBufferOES(GLenum target, GLenum access) { - EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, " - "GLboolean normalized = %d, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)", - index, size, type, normalized, stride, ptr); + EVENT("(GLenum target = 0x%X, GLbitfield access = 0x%X)", target, access); + + gl::Context *context = gl::getNonLostContext(); - try + if (context) { - if (index >= gl::MAX_VERTEX_ATTRIBS) + if (!gl::ValidBufferTarget(context, target)) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_ENUM, reinterpret_cast(NULL)); } - if (size < 1 || size > 4) - { - return gl::error(GL_INVALID_VALUE); - } + gl::Buffer *buffer = context->getState().getTargetBuffer(target); - switch (type) + if (buffer == NULL) { - case GL_BYTE: - case GL_UNSIGNED_BYTE: - case GL_SHORT: - case GL_UNSIGNED_SHORT: - case GL_FIXED: - case GL_FLOAT: - break; - default: - return gl::error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); } - if (stride < 0) + if (access != GL_WRITE_ONLY_OES) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_ENUM, reinterpret_cast(NULL)); } - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (buffer->isMapped()) { - context->setVertexAttribState(index, context->getArrayBuffer(), size, type, (normalized == GL_TRUE), stride, ptr); + return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); } + + return buffer->mapRange(0, buffer->getSize(), GL_MAP_WRITE_BIT); } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } + + return NULL; } -void __stdcall glViewport(GLint x, GLint y, GLsizei width, GLsizei height) +GLboolean __stdcall glUnmapBufferOES(GLenum target) { - EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height); + EVENT("(GLenum target = 0x%X)", target); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - if (width < 0 || height < 0) + if (!gl::ValidBufferTarget(context, target)) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_ENUM, GL_FALSE); } - gl::Context *context = gl::getNonLostContext(); + gl::Buffer *buffer = context->getState().getTargetBuffer(target); - if (context) + if (buffer == NULL || !buffer->isMapped()) { - context->setViewportParams(x, y, width, height); + return gl::error(GL_INVALID_OPERATION, GL_FALSE); } + + // TODO: detect if we had corruption. if so, throw an error and return false. + + buffer->unmap(); + + return GL_TRUE; } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } + + return GL_FALSE; } -void __stdcall glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, - GLbitfield mask, GLenum filter) +void* __stdcall glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) { - EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, " - "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, " - "GLbitfield mask = 0x%X, GLenum filter = 0x%X)", - srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter); + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)", + target, offset, length, access); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - switch (filter) + if (!gl::ValidBufferTarget(context, target)) { - case GL_NEAREST: - break; - default: - return gl::error(GL_INVALID_ENUM); + return gl::error(GL_INVALID_ENUM, reinterpret_cast(NULL)); } - if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0) + if (offset < 0 || length < 0) { - return gl::error(GL_INVALID_VALUE); + return gl::error(GL_INVALID_VALUE, reinterpret_cast(NULL)); } - if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0) + gl::Buffer *buffer = context->getState().getTargetBuffer(target); + + if (buffer == NULL) { - ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation"); - return gl::error(GL_INVALID_OPERATION); + return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); } - gl::Context *context = gl::getNonLostContext(); + // Check for buffer overflow + size_t offsetSize = static_cast(offset); + size_t lengthSize = static_cast(length); - if (context) + if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || + offsetSize + lengthSize > static_cast(buffer->getSize())) { - if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle()) - { - ERR("Blits with the same source and destination framebuffer are not supported by this implementation."); - return gl::error(GL_INVALID_OPERATION); - } - - context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask); + return gl::error(GL_INVALID_VALUE, reinterpret_cast(NULL)); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } -} - -void __stdcall glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, - GLint border, GLenum format, GLenum type, const GLvoid* pixels) -{ - EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, " - "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, " - "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)", - target, level, internalformat, width, height, depth, border, format, type, pixels); - - try - { - UNIMPLEMENTED(); // FIXME - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } -} -void __stdcall glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, - GLenum *binaryFormat, void *binary) -{ - EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)", - program, bufSize, length, binaryFormat, binary); + // Check for invalid bits in the mask + GLbitfield allAccessBits = GL_MAP_READ_BIT | + GL_MAP_WRITE_BIT | + GL_MAP_INVALIDATE_RANGE_BIT | + GL_MAP_INVALIDATE_BUFFER_BIT | + GL_MAP_FLUSH_EXPLICIT_BIT | + GL_MAP_UNSYNCHRONIZED_BIT; - try - { - gl::Context *context = gl::getNonLostContext(); - - if (context) + if (access & ~(allAccessBits)) { - gl::Program *programObject = context->getProgram(program); - - if (!programObject || !programObject->isLinked()) - { - return gl::error(GL_INVALID_OPERATION); - } - - gl::ProgramBinary *programBinary = programObject->getProgramBinary(); - - if (!programBinary) - { - return gl::error(GL_INVALID_OPERATION); - } - - if (!programBinary->save(binary, bufSize, length)) - { - return gl::error(GL_INVALID_OPERATION); - } - - *binaryFormat = GL_PROGRAM_BINARY_ANGLE; + return gl::error(GL_INVALID_VALUE, reinterpret_cast(NULL)); } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } -} -void __stdcall glProgramBinaryOES(GLuint program, GLenum binaryFormat, - const void *binary, GLint length) -{ - EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)", - program, binaryFormat, binary, length); - - try - { - gl::Context *context = gl::getNonLostContext(); + if (length == 0 || buffer->isMapped()) + { + return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); + } - if (context) + // Check for invalid bit combinations + if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0) { - if (binaryFormat != GL_PROGRAM_BINARY_ANGLE) - { - return gl::error(GL_INVALID_ENUM); - } + return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); + } - gl::Program *programObject = context->getProgram(program); + GLbitfield writeOnlyBits = GL_MAP_INVALIDATE_RANGE_BIT | + GL_MAP_INVALIDATE_BUFFER_BIT | + GL_MAP_UNSYNCHRONIZED_BIT; - if (!programObject) - { - return gl::error(GL_INVALID_OPERATION); - } + if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0) + { + return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); + } - context->setProgramBinary(program, binary, length); + if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0) + { + return gl::error(GL_INVALID_OPERATION, reinterpret_cast(NULL)); } + + return buffer->mapRange(offset, length, access); } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); - } + + return NULL; } -void __stdcall glDrawBuffersEXT(GLsizei n, const GLenum *bufs) +void __stdcall glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length) { - EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs); + EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + if (offset < 0 || length < 0) + { + return gl::error(GL_INVALID_VALUE); + } - if (context) + if (!gl::ValidBufferTarget(context, target)) { - if (n < 0 || (unsigned int)n > context->getMaximumRenderTargets()) - { - return gl::error(GL_INVALID_VALUE); - } + return gl::error(GL_INVALID_ENUM); + } - if (context->getDrawFramebufferHandle() == 0) - { - if (n != 1) - { - return gl::error(GL_INVALID_OPERATION); - } + gl::Buffer *buffer = context->getState().getTargetBuffer(target); - if (bufs[0] != GL_NONE && bufs[0] != GL_BACK) - { - return gl::error(GL_INVALID_OPERATION); - } - } - else - { - for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) - { - const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment; - if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment) - { - return gl::error(GL_INVALID_OPERATION); - } - } - } + if (buffer == NULL) + { + return gl::error(GL_INVALID_OPERATION); + } - gl::Framebuffer *framebuffer = context->getDrawFramebuffer(); + if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0) + { + return gl::error(GL_INVALID_OPERATION); + } - for (int colorAttachment = 0; colorAttachment < n; colorAttachment++) - { - framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]); - } + // Check for buffer overflow + size_t offsetSize = static_cast(offset); + size_t lengthSize = static_cast(length); - for (int colorAttachment = n; colorAttachment < (int)context->getMaximumRenderTargets(); colorAttachment++) - { - framebuffer->setDrawBufferState(colorAttachment, GL_NONE); - } + if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) || + offsetSize + lengthSize > static_cast(buffer->getMapLength())) + { + return gl::error(GL_INVALID_VALUE); } - } - catch (std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY); + + // We do not currently support a non-trivial implementation of FlushMappedBufferRange } } @@ -7057,7 +8321,12 @@ __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char * {"glDrawArraysInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawArraysInstancedANGLE}, {"glDrawElementsInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawElementsInstancedANGLE}, {"glGetProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glGetProgramBinaryOES}, - {"glProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glProgramBinaryOES}, }; + {"glProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glProgramBinaryOES}, + {"glGetBufferPointervOES", (__eglMustCastToProperFunctionPointerType)glGetBufferPointervOES}, + {"glMapBufferOES", (__eglMustCastToProperFunctionPointerType)glMapBufferOES}, + {"glUnmapBufferOES", (__eglMustCastToProperFunctionPointerType)glUnmapBufferOES}, + {"glMapBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)glMapBufferRangeEXT}, + {"glFlushMappedBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)glFlushMappedBufferRangeEXT}, }; for (unsigned int ext = 0; ext < ArraySize(glExtensions); ext++) { @@ -7077,28 +8346,19 @@ bool __stdcall glBindTexImage(egl::Surface *surface) EVENT("(egl::Surface* surface = 0x%0.8p)", surface); - try + gl::Context *context = gl::getNonLostContext(); + + if (context) { - gl::Context *context = gl::getNonLostContext(); + gl::Texture2D *textureObject = context->getTexture2D(); + ASSERT(textureObject != NULL); - if (context) + if (textureObject->isImmutable()) { - gl::Texture2D *textureObject = context->getTexture2D(); - - if (textureObject->isImmutable()) - { - return false; - } - - if (textureObject) - { - textureObject->bindTexImage(surface); - } + return false; } - } - catch(std::bad_alloc&) - { - return gl::error(GL_OUT_OF_MEMORY, false); + + textureObject->bindTexImage(surface); } return true; diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def index b8320c8f25..88dceb3556 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def @@ -173,6 +173,117 @@ EXPORTS glProgramBinaryOES @175 glGetProgramBinaryOES @176 glDrawBuffersEXT @179 + glMapBufferOES @285 + glUnmapBufferOES @286 + glGetBufferPointervOES @287 + glMapBufferRangeEXT @288 + glFlushMappedBufferRangeEXT @289 + + ; GLES 3.0 Functions + glReadBuffer @180 + glDrawRangeElements @181 + glTexImage3D @182 + glTexSubImage3D @183 + glCopyTexSubImage3D @184 + glCompressedTexImage3D @185 + glCompressedTexSubImage3D @186 + glGenQueries @187 + glDeleteQueries @188 + glIsQuery @189 + glBeginQuery @190 + glEndQuery @191 + glGetQueryiv @192 + glGetQueryObjectuiv @193 + glUnmapBuffer @194 + glGetBufferPointerv @195 + glDrawBuffers @196 + glUniformMatrix2x3fv @197 + glUniformMatrix3x2fv @198 + glUniformMatrix2x4fv @199 + glUniformMatrix4x2fv @200 + glUniformMatrix3x4fv @201 + glUniformMatrix4x3fv @202 + glBlitFramebuffer @203 + glRenderbufferStorageMultisample @204 + glFramebufferTextureLayer @205 + glMapBufferRange @206 + glFlushMappedBufferRange @207 + glBindVertexArray @208 + glDeleteVertexArrays @209 + glGenVertexArrays @210 + glIsVertexArray @211 + glGetIntegeri_v @212 + glBeginTransformFeedback @213 + glEndTransformFeedback @214 + glBindBufferRange @215 + glBindBufferBase @216 + glTransformFeedbackVaryings @217 + glGetTransformFeedbackVarying @218 + glVertexAttribIPointer @219 + glGetVertexAttribIiv @220 + glGetVertexAttribIuiv @221 + glVertexAttribI4i @222 + glVertexAttribI4ui @223 + glVertexAttribI4iv @224 + glVertexAttribI4uiv @225 + glGetUniformuiv @226 + glGetFragDataLocation @227 + glUniform1ui @228 + glUniform2ui @229 + glUniform3ui @230 + glUniform4ui @231 + glUniform1uiv @232 + glUniform2uiv @233 + glUniform3uiv @234 + glUniform4uiv @235 + glClearBufferiv @236 + glClearBufferuiv @237 + glClearBufferfv @238 + glClearBufferfi @239 + glGetStringi @240 + glCopyBufferSubData @241 + glGetUniformIndices @242 + glGetActiveUniformsiv @243 + glGetUniformBlockIndex @244 + glGetActiveUniformBlockiv @245 + glGetActiveUniformBlockName @246 + glUniformBlockBinding @247 + glDrawArraysInstanced @248 + glDrawElementsInstanced @249 + glFenceSync @250 + glIsSync @251 + glDeleteSync @252 + glClientWaitSync @253 + glWaitSync @254 + glGetInteger64v @255 + glGetSynciv @256 + glGetInteger64i_v @257 + glGetBufferParameteri64v @258 + glGenSamplers @259 + glDeleteSamplers @260 + glIsSampler @261 + glBindSampler @262 + glSamplerParameteri @263 + glSamplerParameteriv @264 + glSamplerParameterf @265 + glSamplerParameterfv @266 + glGetSamplerParameteriv @267 + glGetSamplerParameterfv @268 + glVertexAttribDivisor @269 + glBindTransformFeedback @270 + glDeleteTransformFeedbacks @271 + glGenTransformFeedbacks @272 + glIsTransformFeedback @273 + glPauseTransformFeedback @274 + glResumeTransformFeedback @275 + glGetProgramBinary @276 + glProgramBinary @277 + glProgramParameteri @278 + glInvalidateFramebuffer @279 + glInvalidateSubFramebuffer @280 + glTexStorage2D @281 + glTexStorage3D @282 + glGetInternalformativ @283 ; EGL dependencies glCreateContext @144 NONAME @@ -185,4 +296,4 @@ EXPORTS glDestroyRenderer @178 NONAME ; Setting up TRACE macro callbacks - SetTraceFunctionPointers @180 + SetTraceFunctionPointers @284 diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def index ef44917d71..d6272c4df9 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def @@ -1,188 +1,299 @@ LIBRARY libGLESv2 EXPORTS - glActiveTexture@4 @1 - glAttachShader@8 @2 - glBindAttribLocation@12 @3 - glBindBuffer@8 @4 - glBindFramebuffer@8 @5 - glBindRenderbuffer@8 @6 - glBindTexture@8 @7 - glBlendColor@16 @8 - glBlendEquation@4 @9 - glBlendEquationSeparate@8 @10 - glBlendFunc@8 @11 - glBlendFuncSeparate@16 @12 - glBufferData@16 @13 - glBufferSubData@16 @14 - glCheckFramebufferStatus@4 @15 - glClear@4 @16 - glClearColor@16 @17 - glClearDepthf@4 @18 - glClearStencil@4 @19 - glColorMask@16 @20 - glCompileShader@4 @21 - glCompressedTexImage2D@32 @22 - glCompressedTexSubImage2D@36 @23 - glCopyTexImage2D@32 @24 - glCopyTexSubImage2D@32 @25 - glCreateProgram@0 @26 - glCreateShader@4 @27 - glCullFace@4 @28 - glDeleteBuffers@8 @29 - glDeleteFramebuffers@8 @30 - glDeleteProgram@4 @32 - glDeleteRenderbuffers@8 @33 - glDeleteShader@4 @34 - glDeleteTextures@8 @31 - glDepthFunc@4 @36 - glDepthMask@4 @37 - glDepthRangef@8 @38 - glDetachShader@8 @35 - glDisable@4 @39 - glDisableVertexAttribArray@4 @40 - glDrawArrays@12 @41 - glDrawElements@16 @42 - glEnable@4 @43 - glEnableVertexAttribArray@4 @44 - glFinish@0 @45 - glFlush@0 @46 - glFramebufferRenderbuffer@16 @47 - glFramebufferTexture2D@20 @48 - glFrontFace@4 @49 - glGenBuffers@8 @50 - glGenFramebuffers@8 @52 - glGenRenderbuffers@8 @53 - glGenTextures@8 @54 - glGenerateMipmap@4 @51 - glGetActiveAttrib@28 @55 - glGetActiveUniform@28 @56 - glGetAttachedShaders@16 @57 - glGetAttribLocation@8 @58 - glGetBooleanv@8 @59 - glGetBufferParameteriv@12 @60 - glGetError@0 @61 - glGetFloatv@8 @62 - glGetFramebufferAttachmentParameteriv@16 @63 - glGetIntegerv@8 @64 - glGetProgramInfoLog@16 @66 - glGetProgramiv@12 @65 - glGetRenderbufferParameteriv@12 @67 - glGetShaderInfoLog@16 @69 - glGetShaderPrecisionFormat@16 @70 - glGetShaderSource@16 @71 - glGetShaderiv@12 @68 - glGetString@4 @72 - glGetTexParameterfv@12 @73 - glGetTexParameteriv@12 @74 - glGetUniformLocation@8 @77 - glGetUniformfv@12 @75 - glGetUniformiv@12 @76 - glGetVertexAttribPointerv@12 @80 - glGetVertexAttribfv@12 @78 - glGetVertexAttribiv@12 @79 - glHint@8 @81 - glIsBuffer@4 @82 - glIsEnabled@4 @83 - glIsFramebuffer@4 @84 - glIsProgram@4 @85 - glIsRenderbuffer@4 @86 - glIsShader@4 @87 - glIsTexture@4 @88 - glLineWidth@4 @89 - glLinkProgram@4 @90 - glPixelStorei@8 @91 - glPolygonOffset@8 @92 - glReadPixels@28 @93 - glReleaseShaderCompiler@0 @94 - glRenderbufferStorage@16 @95 - glSampleCoverage@8 @96 - glScissor@16 @97 - glShaderBinary@20 @98 - glShaderSource@16 @99 - glStencilFunc@12 @100 - glStencilFuncSeparate@16 @101 - glStencilMask@4 @102 - glStencilMaskSeparate@8 @103 - glStencilOp@12 @104 - glStencilOpSeparate@16 @105 - glTexImage2D@36 @106 - glTexParameterf@12 @107 - glTexParameterfv@12 @108 - glTexParameteri@12 @109 - glTexParameteriv@12 @110 - glTexSubImage2D@36 @111 - glUniform1f@8 @112 - glUniform1fv@12 @113 - glUniform1i@8 @114 - glUniform1iv@12 @115 - glUniform2f@12 @116 - glUniform2fv@12 @117 - glUniform2i@12 @118 - glUniform2iv@12 @119 - glUniform3f@16 @120 - glUniform3fv@12 @121 - glUniform3i@16 @122 - glUniform3iv@12 @123 - glUniform4f@20 @124 - glUniform4fv@12 @125 - glUniform4i@20 @126 - glUniform4iv@12 @127 - glUniformMatrix2fv@16 @128 - glUniformMatrix3fv@16 @129 - glUniformMatrix4fv@16 @130 - glUseProgram@4 @131 - glValidateProgram@4 @132 - glVertexAttrib1f@8 @133 - glVertexAttrib1fv@8 @134 - glVertexAttrib2f@12 @135 - glVertexAttrib2fv@8 @136 - glVertexAttrib3f@16 @137 - glVertexAttrib3fv@8 @138 - glVertexAttrib4f@20 @139 - glVertexAttrib4fv@8 @140 - glVertexAttribPointer@24 @141 - glViewport@16 @142 + glActiveTexture@4 @1 + glAttachShader@8 @2 + glBindAttribLocation@12 @3 + glBindBuffer@8 @4 + glBindFramebuffer@8 @5 + glBindRenderbuffer@8 @6 + glBindTexture@8 @7 + glBlendColor@16 @8 + glBlendEquation@4 @9 + glBlendEquationSeparate@8 @10 + glBlendFunc@8 @11 + glBlendFuncSeparate@16 @12 + glBufferData@16 @13 + glBufferSubData@16 @14 + glCheckFramebufferStatus@4 @15 + glClear@4 @16 + glClearColor@16 @17 + glClearDepthf@4 @18 + glClearStencil@4 @19 + glColorMask@16 @20 + glCompileShader@4 @21 + glCompressedTexImage2D@32 @22 + glCompressedTexSubImage2D@36 @23 + glCopyTexImage2D@32 @24 + glCopyTexSubImage2D@32 @25 + glCreateProgram@0 @26 + glCreateShader@4 @27 + glCullFace@4 @28 + glDeleteBuffers@8 @29 + glDeleteFramebuffers@8 @30 + glDeleteProgram@4 @32 + glDeleteRenderbuffers@8 @33 + glDeleteShader@4 @34 + glDeleteTextures@8 @31 + glDepthFunc@4 @36 + glDepthMask@4 @37 + glDepthRangef@8 @38 + glDetachShader@8 @35 + glDisable@4 @39 + glDisableVertexAttribArray@4 @40 + glDrawArrays@12 @41 + glDrawElements@16 @42 + glEnable@4 @43 + glEnableVertexAttribArray@4 @44 + glFinish@0 @45 + glFlush@0 @46 + glFramebufferRenderbuffer@16 @47 + glFramebufferTexture2D@20 @48 + glFrontFace@4 @49 + glGenBuffers@8 @50 + glGenFramebuffers@8 @52 + glGenRenderbuffers@8 @53 + glGenTextures@8 @54 + glGenerateMipmap@4 @51 + glGetActiveAttrib@28 @55 + glGetActiveUniform@28 @56 + glGetAttachedShaders@16 @57 + glGetAttribLocation@8 @58 + glGetBooleanv@8 @59 + glGetBufferParameteriv@12 @60 + glGetError@0 @61 + glGetFloatv@8 @62 + glGetFramebufferAttachmentParameteriv@16 @63 + glGetIntegerv@8 @64 + glGetProgramInfoLog@16 @66 + glGetProgramiv@12 @65 + glGetRenderbufferParameteriv@12 @67 + glGetShaderInfoLog@16 @69 + glGetShaderPrecisionFormat@16 @70 + glGetShaderSource@16 @71 + glGetShaderiv@12 @68 + glGetString@4 @72 + glGetTexParameterfv@12 @73 + glGetTexParameteriv@12 @74 + glGetUniformLocation@8 @77 + glGetUniformfv@12 @75 + glGetUniformiv@12 @76 + glGetVertexAttribPointerv@12 @80 + glGetVertexAttribfv@12 @78 + glGetVertexAttribiv@12 @79 + glHint@8 @81 + glIsBuffer@4 @82 + glIsEnabled@4 @83 + glIsFramebuffer@4 @84 + glIsProgram@4 @85 + glIsRenderbuffer@4 @86 + glIsShader@4 @87 + glIsTexture@4 @88 + glLineWidth@4 @89 + glLinkProgram@4 @90 + glPixelStorei@8 @91 + glPolygonOffset@8 @92 + glReadPixels@28 @93 + glReleaseShaderCompiler@0 @94 + glRenderbufferStorage@16 @95 + glSampleCoverage@8 @96 + glScissor@16 @97 + glShaderBinary@20 @98 + glShaderSource@16 @99 + glStencilFunc@12 @100 + glStencilFuncSeparate@16 @101 + glStencilMask@4 @102 + glStencilMaskSeparate@8 @103 + glStencilOp@12 @104 + glStencilOpSeparate@16 @105 + glTexImage2D@36 @106 + glTexParameterf@12 @107 + glTexParameterfv@12 @108 + glTexParameteri@12 @109 + glTexParameteriv@12 @110 + glTexSubImage2D@36 @111 + glUniform1f@8 @112 + glUniform1fv@12 @113 + glUniform1i@8 @114 + glUniform1iv@12 @115 + glUniform2f@12 @116 + glUniform2fv@12 @117 + glUniform2i@12 @118 + glUniform2iv@12 @119 + glUniform3f@16 @120 + glUniform3fv@12 @121 + glUniform3i@16 @122 + glUniform3iv@12 @123 + glUniform4f@20 @124 + glUniform4fv@12 @125 + glUniform4i@20 @126 + glUniform4iv@12 @127 + glUniformMatrix2fv@16 @128 + glUniformMatrix3fv@16 @129 + glUniformMatrix4fv@16 @130 + glUseProgram@4 @131 + glValidateProgram@4 @132 + glVertexAttrib1f@8 @133 + glVertexAttrib1fv@8 @134 + glVertexAttrib2f@12 @135 + glVertexAttrib2fv@8 @136 + glVertexAttrib3f@16 @137 + glVertexAttrib3fv@8 @138 + glVertexAttrib4f@20 @139 + glVertexAttrib4fv@8 @140 + glVertexAttribPointer@24 @141 + glViewport@16 @142 - ; Extensions - glTexImage3DOES@40 @143 - glBlitFramebufferANGLE@40 @149 - glRenderbufferStorageMultisampleANGLE@20 @150 - glDeleteFencesNV@8 @151 - glFinishFenceNV@4 @152 - glGenFencesNV@8 @153 - glGetFenceivNV@12 @154 - glIsFenceNV@4 @155 - glSetFenceNV@8 @156 - glTestFenceNV@4 @157 - glGetTranslatedShaderSourceANGLE@16 @159 - glTexStorage2DEXT@20 @160 - glGetGraphicsResetStatusEXT@0 @161 - glReadnPixelsEXT@32 @162 - glGetnUniformfvEXT@16 @163 - glGetnUniformivEXT@16 @164 - glGenQueriesEXT@8 @165 - glDeleteQueriesEXT@8 @166 - glIsQueryEXT@4 @167 - glBeginQueryEXT@8 @168 - glEndQueryEXT@4 @169 - glGetQueryivEXT@12 @170 - glGetQueryObjectuivEXT@12 @171 - glVertexAttribDivisorANGLE@8 @172 - glDrawArraysInstancedANGLE@16 @173 - glDrawElementsInstancedANGLE@20 @174 - glProgramBinaryOES@16 @175 - glGetProgramBinaryOES@20 @176 - glDrawBuffersEXT@8 @179 + ; Extensions + glTexImage3DOES@40 @143 + glBlitFramebufferANGLE@40 @149 + glRenderbufferStorageMultisampleANGLE@20 @150 + glDeleteFencesNV@8 @151 + glFinishFenceNV@4 @152 + glGenFencesNV@8 @153 + glGetFenceivNV@12 @154 + glIsFenceNV@4 @155 + glSetFenceNV@8 @156 + glTestFenceNV@4 @157 + glGetTranslatedShaderSourceANGLE@16 @159 + glTexStorage2DEXT@20 @160 + glGetGraphicsResetStatusEXT@0 @161 + glReadnPixelsEXT@32 @162 + glGetnUniformfvEXT@16 @163 + glGetnUniformivEXT@16 @164 + glGenQueriesEXT@8 @165 + glDeleteQueriesEXT@8 @166 + glIsQueryEXT@4 @167 + glBeginQueryEXT@8 @168 + glEndQueryEXT@4 @169 + glGetQueryivEXT@12 @170 + glGetQueryObjectuivEXT@12 @171 + glVertexAttribDivisorANGLE@8 @172 + glDrawArraysInstancedANGLE@16 @173 + glDrawElementsInstancedANGLE@20 @174 + glProgramBinaryOES@16 @175 + glGetProgramBinaryOES@20 @176 + glDrawBuffersEXT@8 @179 + glMapBufferOES@8 @285 + glUnmapBufferOES@4 @286 + glGetBufferPointervOES@12 @287 + glMapBufferRangeEXT@16 @288 + glFlushMappedBufferRangeEXT@12 @289 - ; EGL dependencies - glCreateContext @144 NONAME - glDestroyContext @145 NONAME - glMakeCurrent @146 NONAME - glGetCurrentContext @147 NONAME - glGetProcAddress@4 @148 NONAME - glBindTexImage@4 @158 NONAME - glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME + ; GLES 3.0 Functions + glReadBuffer@4 @180 + glDrawRangeElements@24 @181 + glTexImage3D@40 @182 + glTexSubImage3D@44 @183 + glCopyTexSubImage3D@36 @184 + glCompressedTexImage3D@36 @185 + glCompressedTexSubImage3D@44 @186 + glGenQueries@8 @187 + glDeleteQueries@8 @188 + glIsQuery@4 @189 + glBeginQuery@8 @190 + glEndQuery@4 @191 + glGetQueryiv@12 @192 + glGetQueryObjectuiv@12 @193 + glUnmapBuffer@4 @194 + glGetBufferPointerv@12 @195 + glDrawBuffers@8 @196 + glUniformMatrix2x3fv@16 @197 + glUniformMatrix3x2fv@16 @198 + glUniformMatrix2x4fv@16 @199 + glUniformMatrix4x2fv@16 @200 + glUniformMatrix3x4fv@16 @201 + glUniformMatrix4x3fv@16 @202 + glBlitFramebuffer@40 @203 + glRenderbufferStorageMultisample@20 @204 + glFramebufferTextureLayer@20 @205 + glMapBufferRange@16 @206 + glFlushMappedBufferRange@12 @207 + glBindVertexArray@4 @208 + glDeleteVertexArrays@8 @209 + glGenVertexArrays@8 @210 + glIsVertexArray@4 @211 + glGetIntegeri_v@12 @212 + glBeginTransformFeedback@4 @213 + glEndTransformFeedback@0 @214 + glBindBufferRange@20 @215 + glBindBufferBase@12 @216 + glTransformFeedbackVaryings@16 @217 + glGetTransformFeedbackVarying@28 @218 + glVertexAttribIPointer@20 @219 + glGetVertexAttribIiv@12 @220 + glGetVertexAttribIuiv@12 @221 + glVertexAttribI4i@20 @222 + glVertexAttribI4ui@20 @223 + glVertexAttribI4iv@8 @224 + glVertexAttribI4uiv@8 @225 + glGetUniformuiv@12 @226 + glGetFragDataLocation@8 @227 + glUniform1ui@8 @228 + glUniform2ui@12 @229 + glUniform3ui@16 @230 + glUniform4ui@20 @231 + glUniform1uiv@12 @232 + glUniform2uiv@12 @233 + glUniform3uiv@12 @234 + glUniform4uiv@12 @235 + glClearBufferiv@12 @236 + glClearBufferuiv@12 @237 + glClearBufferfv@12 @238 + glClearBufferfi@16 @239 + glGetStringi@8 @240 + glCopyBufferSubData@20 @241 + glGetUniformIndices@16 @242 + glGetActiveUniformsiv@20 @243 + glGetUniformBlockIndex@8 @244 + glGetActiveUniformBlockiv@16 @245 + glGetActiveUniformBlockName@20 @246 + glUniformBlockBinding@12 @247 + glDrawArraysInstanced@16 @248 + glDrawElementsInstanced@20 @249 + glFenceSync@8 @250 + glIsSync@4 @251 + glDeleteSync@4 @252 + glClientWaitSync@16 @253 + glWaitSync@16 @254 + glGetInteger64v@8 @255 + glGetSynciv@20 @256 + glGetInteger64i_v@12 @257 + glGetBufferParameteri64v@12 @258 + glGenSamplers@8 @259 + glDeleteSamplers@8 @260 + glIsSampler@4 @261 + glBindSampler@8 @262 + glSamplerParameteri@12 @263 + glSamplerParameteriv@12 @264 + glSamplerParameterf@12 @265 + glSamplerParameterfv@12 @266 + glGetSamplerParameteriv@12 @267 + glGetSamplerParameterfv@12 @268 + glVertexAttribDivisor@8 @269 + glBindTransformFeedback@8 @270 + glDeleteTransformFeedbacks@8 @271 + glGenTransformFeedbacks@8 @272 + glIsTransformFeedback@4 @273 + glPauseTransformFeedback@0 @274 + glResumeTransformFeedback@0 @275 + glGetProgramBinary@20 @276 + glProgramBinary@16 @277 + glProgramParameteri@12 @278 + glInvalidateFramebuffer@12 @279 + glInvalidateSubFramebuffer@28 @280 + glTexStorage2D@20 @281 + glTexStorage3D@24 @282 + glGetInternalformativ@20 @283 - ; Setting up TRACE macro callbacks - SetTraceFunctionPointers@8 @180 + ; EGL dependencies + glCreateContext @144 NONAME + glDestroyContext @145 NONAME + glMakeCurrent @146 NONAME + glGetCurrentContext @147 NONAME + glGetProcAddress@4 @148 NONAME + glBindTexImage@4 @158 NONAME + glCreateRenderer @177 NONAME + glDestroyRenderer @178 NONAME + + ; Setting up TRACE macro callbacks + SetTraceFunctionPointers@8 @284 diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def index 3dd5683b5f..d301aa0905 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def @@ -173,6 +173,117 @@ EXPORTS glProgramBinaryOES @175 glGetProgramBinaryOES @176 glDrawBuffersEXT @179 + glMapBufferOES @285 + glUnmapBufferOES @286 + glGetBufferPointervOES @287 + glMapBufferRangeEXT @288 + glFlushMappedBufferRangeEXT @289 + + ; GLES 3.0 Functions + glReadBuffer @180 + glDrawRangeElements @181 + glTexImage3D @182 + glTexSubImage3D @183 + glCopyTexSubImage3D @184 + glCompressedTexImage3D @185 + glCompressedTexSubImage3D @186 + glGenQueries @187 + glDeleteQueries @188 + glIsQuery @189 + glBeginQuery @190 + glEndQuery @191 + glGetQueryiv @192 + glGetQueryObjectuiv @193 + glUnmapBuffer @194 + glGetBufferPointerv @195 + glDrawBuffers @196 + glUniformMatrix2x3fv @197 + glUniformMatrix3x2fv @198 + glUniformMatrix2x4fv @199 + glUniformMatrix4x2fv @200 + glUniformMatrix3x4fv @201 + glUniformMatrix4x3fv @202 + glBlitFramebuffer @203 + glRenderbufferStorageMultisample @204 + glFramebufferTextureLayer @205 + glMapBufferRange @206 + glFlushMappedBufferRange @207 + glBindVertexArray @208 + glDeleteVertexArrays @209 + glGenVertexArrays @210 + glIsVertexArray @211 + glGetIntegeri_v @212 + glBeginTransformFeedback @213 + glEndTransformFeedback @214 + glBindBufferRange @215 + glBindBufferBase @216 + glTransformFeedbackVaryings @217 + glGetTransformFeedbackVarying @218 + glVertexAttribIPointer @219 + glGetVertexAttribIiv @220 + glGetVertexAttribIuiv @221 + glVertexAttribI4i @222 + glVertexAttribI4ui @223 + glVertexAttribI4iv @224 + glVertexAttribI4uiv @225 + glGetUniformuiv @226 + glGetFragDataLocation @227 + glUniform1ui @228 + glUniform2ui @229 + glUniform3ui @230 + glUniform4ui @231 + glUniform1uiv @232 + glUniform2uiv @233 + glUniform3uiv @234 + glUniform4uiv @235 + glClearBufferiv @236 + glClearBufferuiv @237 + glClearBufferfv @238 + glClearBufferfi @239 + glGetStringi @240 + glCopyBufferSubData @241 + glGetUniformIndices @242 + glGetActiveUniformsiv @243 + glGetUniformBlockIndex @244 + glGetActiveUniformBlockiv @245 + glGetActiveUniformBlockName @246 + glUniformBlockBinding @247 + glDrawArraysInstanced @248 + glDrawElementsInstanced @249 + glFenceSync @250 + glIsSync @251 + glDeleteSync @252 + glClientWaitSync @253 + glWaitSync @254 + glGetInteger64v @255 + glGetSynciv @256 + glGetInteger64i_v @257 + glGetBufferParameteri64v @258 + glGenSamplers @259 + glDeleteSamplers @260 + glIsSampler @261 + glBindSampler @262 + glSamplerParameteri @263 + glSamplerParameteriv @264 + glSamplerParameterf @265 + glSamplerParameterfv @266 + glGetSamplerParameteriv @267 + glGetSamplerParameterfv @268 + glVertexAttribDivisor @269 + glBindTransformFeedback @270 + glDeleteTransformFeedbacks @271 + glGenTransformFeedbacks @272 + glIsTransformFeedback @273 + glPauseTransformFeedback @274 + glResumeTransformFeedback @275 + glGetProgramBinary @276 + glProgramBinary @277 + glProgramParameteri @278 + glInvalidateFramebuffer @279 + glInvalidateSubFramebuffer @280 + glTexStorage2D @281 + glTexStorage3D @282 + glGetInternalformativ @283 ; EGL dependencies glCreateContext @144 NONAME @@ -185,4 +296,4 @@ EXPORTS glDestroyRenderer @178 NONAME ; Setting up TRACE macro callbacks - SetTraceFunctionPointers @180 + SetTraceFunctionPointers @284 diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def index 6c8d3ed630..a82d629ae4 100644 --- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def +++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def @@ -1,188 +1,299 @@ LIBRARY libGLESv2d EXPORTS - glActiveTexture@4 @1 - glAttachShader@8 @2 - glBindAttribLocation@12 @3 - glBindBuffer@8 @4 - glBindFramebuffer@8 @5 - glBindRenderbuffer@8 @6 - glBindTexture@8 @7 - glBlendColor@16 @8 - glBlendEquation@4 @9 - glBlendEquationSeparate@8 @10 - glBlendFunc@8 @11 - glBlendFuncSeparate@16 @12 - glBufferData@16 @13 - glBufferSubData@16 @14 - glCheckFramebufferStatus@4 @15 - glClear@4 @16 - glClearColor@16 @17 - glClearDepthf@4 @18 - glClearStencil@4 @19 - glColorMask@16 @20 - glCompileShader@4 @21 - glCompressedTexImage2D@32 @22 - glCompressedTexSubImage2D@36 @23 - glCopyTexImage2D@32 @24 - glCopyTexSubImage2D@32 @25 - glCreateProgram@0 @26 - glCreateShader@4 @27 - glCullFace@4 @28 - glDeleteBuffers@8 @29 - glDeleteFramebuffers@8 @30 - glDeleteProgram@4 @32 - glDeleteRenderbuffers@8 @33 - glDeleteShader@4 @34 - glDeleteTextures@8 @31 - glDepthFunc@4 @36 - glDepthMask@4 @37 - glDepthRangef@8 @38 - glDetachShader@8 @35 - glDisable@4 @39 - glDisableVertexAttribArray@4 @40 - glDrawArrays@12 @41 - glDrawElements@16 @42 - glEnable@4 @43 - glEnableVertexAttribArray@4 @44 - glFinish@0 @45 - glFlush@0 @46 - glFramebufferRenderbuffer@16 @47 - glFramebufferTexture2D@20 @48 - glFrontFace@4 @49 - glGenBuffers@8 @50 - glGenFramebuffers@8 @52 - glGenRenderbuffers@8 @53 - glGenTextures@8 @54 - glGenerateMipmap@4 @51 - glGetActiveAttrib@28 @55 - glGetActiveUniform@28 @56 - glGetAttachedShaders@16 @57 - glGetAttribLocation@8 @58 - glGetBooleanv@8 @59 - glGetBufferParameteriv@12 @60 - glGetError@0 @61 - glGetFloatv@8 @62 - glGetFramebufferAttachmentParameteriv@16 @63 - glGetIntegerv@8 @64 - glGetProgramInfoLog@16 @66 - glGetProgramiv@12 @65 - glGetRenderbufferParameteriv@12 @67 - glGetShaderInfoLog@16 @69 - glGetShaderPrecisionFormat@16 @70 - glGetShaderSource@16 @71 - glGetShaderiv@12 @68 - glGetString@4 @72 - glGetTexParameterfv@12 @73 - glGetTexParameteriv@12 @74 - glGetUniformLocation@8 @77 - glGetUniformfv@12 @75 - glGetUniformiv@12 @76 - glGetVertexAttribPointerv@12 @80 - glGetVertexAttribfv@12 @78 - glGetVertexAttribiv@12 @79 - glHint@8 @81 - glIsBuffer@4 @82 - glIsEnabled@4 @83 - glIsFramebuffer@4 @84 - glIsProgram@4 @85 - glIsRenderbuffer@4 @86 - glIsShader@4 @87 - glIsTexture@4 @88 - glLineWidth@4 @89 - glLinkProgram@4 @90 - glPixelStorei@8 @91 - glPolygonOffset@8 @92 - glReadPixels@28 @93 - glReleaseShaderCompiler@0 @94 - glRenderbufferStorage@16 @95 - glSampleCoverage@8 @96 - glScissor@16 @97 - glShaderBinary@20 @98 - glShaderSource@16 @99 - glStencilFunc@12 @100 - glStencilFuncSeparate@16 @101 - glStencilMask@4 @102 - glStencilMaskSeparate@8 @103 - glStencilOp@12 @104 - glStencilOpSeparate@16 @105 - glTexImage2D@36 @106 - glTexParameterf@12 @107 - glTexParameterfv@12 @108 - glTexParameteri@12 @109 - glTexParameteriv@12 @110 - glTexSubImage2D@36 @111 - glUniform1f@8 @112 - glUniform1fv@12 @113 - glUniform1i@8 @114 - glUniform1iv@12 @115 - glUniform2f@12 @116 - glUniform2fv@12 @117 - glUniform2i@12 @118 - glUniform2iv@12 @119 - glUniform3f@16 @120 - glUniform3fv@12 @121 - glUniform3i@16 @122 - glUniform3iv@12 @123 - glUniform4f@20 @124 - glUniform4fv@12 @125 - glUniform4i@20 @126 - glUniform4iv@12 @127 - glUniformMatrix2fv@16 @128 - glUniformMatrix3fv@16 @129 - glUniformMatrix4fv@16 @130 - glUseProgram@4 @131 - glValidateProgram@4 @132 - glVertexAttrib1f@8 @133 - glVertexAttrib1fv@8 @134 - glVertexAttrib2f@12 @135 - glVertexAttrib2fv@8 @136 - glVertexAttrib3f@16 @137 - glVertexAttrib3fv@8 @138 - glVertexAttrib4f@20 @139 - glVertexAttrib4fv@8 @140 - glVertexAttribPointer@24 @141 - glViewport@16 @142 + glActiveTexture@4 @1 + glAttachShader@8 @2 + glBindAttribLocation@12 @3 + glBindBuffer@8 @4 + glBindFramebuffer@8 @5 + glBindRenderbuffer@8 @6 + glBindTexture@8 @7 + glBlendColor@16 @8 + glBlendEquation@4 @9 + glBlendEquationSeparate@8 @10 + glBlendFunc@8 @11 + glBlendFuncSeparate@16 @12 + glBufferData@16 @13 + glBufferSubData@16 @14 + glCheckFramebufferStatus@4 @15 + glClear@4 @16 + glClearColor@16 @17 + glClearDepthf@4 @18 + glClearStencil@4 @19 + glColorMask@16 @20 + glCompileShader@4 @21 + glCompressedTexImage2D@32 @22 + glCompressedTexSubImage2D@36 @23 + glCopyTexImage2D@32 @24 + glCopyTexSubImage2D@32 @25 + glCreateProgram@0 @26 + glCreateShader@4 @27 + glCullFace@4 @28 + glDeleteBuffers@8 @29 + glDeleteFramebuffers@8 @30 + glDeleteProgram@4 @32 + glDeleteRenderbuffers@8 @33 + glDeleteShader@4 @34 + glDeleteTextures@8 @31 + glDepthFunc@4 @36 + glDepthMask@4 @37 + glDepthRangef@8 @38 + glDetachShader@8 @35 + glDisable@4 @39 + glDisableVertexAttribArray@4 @40 + glDrawArrays@12 @41 + glDrawElements@16 @42 + glEnable@4 @43 + glEnableVertexAttribArray@4 @44 + glFinish@0 @45 + glFlush@0 @46 + glFramebufferRenderbuffer@16 @47 + glFramebufferTexture2D@20 @48 + glFrontFace@4 @49 + glGenBuffers@8 @50 + glGenFramebuffers@8 @52 + glGenRenderbuffers@8 @53 + glGenTextures@8 @54 + glGenerateMipmap@4 @51 + glGetActiveAttrib@28 @55 + glGetActiveUniform@28 @56 + glGetAttachedShaders@16 @57 + glGetAttribLocation@8 @58 + glGetBooleanv@8 @59 + glGetBufferParameteriv@12 @60 + glGetError@0 @61 + glGetFloatv@8 @62 + glGetFramebufferAttachmentParameteriv@16 @63 + glGetIntegerv@8 @64 + glGetProgramInfoLog@16 @66 + glGetProgramiv@12 @65 + glGetRenderbufferParameteriv@12 @67 + glGetShaderInfoLog@16 @69 + glGetShaderPrecisionFormat@16 @70 + glGetShaderSource@16 @71 + glGetShaderiv@12 @68 + glGetString@4 @72 + glGetTexParameterfv@12 @73 + glGetTexParameteriv@12 @74 + glGetUniformLocation@8 @77 + glGetUniformfv@12 @75 + glGetUniformiv@12 @76 + glGetVertexAttribPointerv@12 @80 + glGetVertexAttribfv@12 @78 + glGetVertexAttribiv@12 @79 + glHint@8 @81 + glIsBuffer@4 @82 + glIsEnabled@4 @83 + glIsFramebuffer@4 @84 + glIsProgram@4 @85 + glIsRenderbuffer@4 @86 + glIsShader@4 @87 + glIsTexture@4 @88 + glLineWidth@4 @89 + glLinkProgram@4 @90 + glPixelStorei@8 @91 + glPolygonOffset@8 @92 + glReadPixels@28 @93 + glReleaseShaderCompiler@0 @94 + glRenderbufferStorage@16 @95 + glSampleCoverage@8 @96 + glScissor@16 @97 + glShaderBinary@20 @98 + glShaderSource@16 @99 + glStencilFunc@12 @100 + glStencilFuncSeparate@16 @101 + glStencilMask@4 @102 + glStencilMaskSeparate@8 @103 + glStencilOp@12 @104 + glStencilOpSeparate@16 @105 + glTexImage2D@36 @106 + glTexParameterf@12 @107 + glTexParameterfv@12 @108 + glTexParameteri@12 @109 + glTexParameteriv@12 @110 + glTexSubImage2D@36 @111 + glUniform1f@8 @112 + glUniform1fv@12 @113 + glUniform1i@8 @114 + glUniform1iv@12 @115 + glUniform2f@12 @116 + glUniform2fv@12 @117 + glUniform2i@12 @118 + glUniform2iv@12 @119 + glUniform3f@16 @120 + glUniform3fv@12 @121 + glUniform3i@16 @122 + glUniform3iv@12 @123 + glUniform4f@20 @124 + glUniform4fv@12 @125 + glUniform4i@20 @126 + glUniform4iv@12 @127 + glUniformMatrix2fv@16 @128 + glUniformMatrix3fv@16 @129 + glUniformMatrix4fv@16 @130 + glUseProgram@4 @131 + glValidateProgram@4 @132 + glVertexAttrib1f@8 @133 + glVertexAttrib1fv@8 @134 + glVertexAttrib2f@12 @135 + glVertexAttrib2fv@8 @136 + glVertexAttrib3f@16 @137 + glVertexAttrib3fv@8 @138 + glVertexAttrib4f@20 @139 + glVertexAttrib4fv@8 @140 + glVertexAttribPointer@24 @141 + glViewport@16 @142 - ; Extensions - glTexImage3DOES@40 @143 - glBlitFramebufferANGLE@40 @149 - glRenderbufferStorageMultisampleANGLE@20 @150 - glDeleteFencesNV@8 @151 - glFinishFenceNV@4 @152 - glGenFencesNV@8 @153 - glGetFenceivNV@12 @154 - glIsFenceNV@4 @155 - glSetFenceNV@8 @156 - glTestFenceNV@4 @157 - glGetTranslatedShaderSourceANGLE@16 @159 - glTexStorage2DEXT@20 @160 - glGetGraphicsResetStatusEXT@0 @161 - glReadnPixelsEXT@32 @162 - glGetnUniformfvEXT@16 @163 - glGetnUniformivEXT@16 @164 - glGenQueriesEXT@8 @165 - glDeleteQueriesEXT@8 @166 - glIsQueryEXT@4 @167 - glBeginQueryEXT@8 @168 - glEndQueryEXT@4 @169 - glGetQueryivEXT@12 @170 - glGetQueryObjectuivEXT@12 @171 - glVertexAttribDivisorANGLE@8 @172 - glDrawArraysInstancedANGLE@16 @173 - glDrawElementsInstancedANGLE@20 @174 - glProgramBinaryOES@16 @175 - glGetProgramBinaryOES@20 @176 - glDrawBuffersEXT@8 @179 + ; Extensions + glTexImage3DOES@40 @143 + glBlitFramebufferANGLE@40 @149 + glRenderbufferStorageMultisampleANGLE@20 @150 + glDeleteFencesNV@8 @151 + glFinishFenceNV@4 @152 + glGenFencesNV@8 @153 + glGetFenceivNV@12 @154 + glIsFenceNV@4 @155 + glSetFenceNV@8 @156 + glTestFenceNV@4 @157 + glGetTranslatedShaderSourceANGLE@16 @159 + glTexStorage2DEXT@20 @160 + glGetGraphicsResetStatusEXT@0 @161 + glReadnPixelsEXT@32 @162 + glGetnUniformfvEXT@16 @163 + glGetnUniformivEXT@16 @164 + glGenQueriesEXT@8 @165 + glDeleteQueriesEXT@8 @166 + glIsQueryEXT@4 @167 + glBeginQueryEXT@8 @168 + glEndQueryEXT@4 @169 + glGetQueryivEXT@12 @170 + glGetQueryObjectuivEXT@12 @171 + glVertexAttribDivisorANGLE@8 @172 + glDrawArraysInstancedANGLE@16 @173 + glDrawElementsInstancedANGLE@20 @174 + glProgramBinaryOES@16 @175 + glGetProgramBinaryOES@20 @176 + glDrawBuffersEXT@8 @179 + glMapBufferOES@8 @285 + glUnmapBufferOES@4 @286 + glGetBufferPointervOES@12 @287 + glMapBufferRangeEXT@16 @288 + glFlushMappedBufferRangeEXT@12 @289 - ; EGL dependencies - glCreateContext @144 NONAME - glDestroyContext @145 NONAME - glMakeCurrent @146 NONAME - glGetCurrentContext @147 NONAME - glGetProcAddress@4 @148 NONAME - glBindTexImage@4 @158 NONAME - glCreateRenderer @177 NONAME - glDestroyRenderer @178 NONAME + ; GLES 3.0 Functions + glReadBuffer@4 @180 + glDrawRangeElements@24 @181 + glTexImage3D@40 @182 + glTexSubImage3D@44 @183 + glCopyTexSubImage3D@36 @184 + glCompressedTexImage3D@36 @185 + glCompressedTexSubImage3D@44 @186 + glGenQueries@8 @187 + glDeleteQueries@8 @188 + glIsQuery@4 @189 + glBeginQuery@8 @190 + glEndQuery@4 @191 + glGetQueryiv@12 @192 + glGetQueryObjectuiv@12 @193 + glUnmapBuffer@4 @194 + glGetBufferPointerv@12 @195 + glDrawBuffers@8 @196 + glUniformMatrix2x3fv@16 @197 + glUniformMatrix3x2fv@16 @198 + glUniformMatrix2x4fv@16 @199 + glUniformMatrix4x2fv@16 @200 + glUniformMatrix3x4fv@16 @201 + glUniformMatrix4x3fv@16 @202 + glBlitFramebuffer@40 @203 + glRenderbufferStorageMultisample@20 @204 + glFramebufferTextureLayer@20 @205 + glMapBufferRange@16 @206 + glFlushMappedBufferRange@12 @207 + glBindVertexArray@4 @208 + glDeleteVertexArrays@8 @209 + glGenVertexArrays@8 @210 + glIsVertexArray@4 @211 + glGetIntegeri_v@12 @212 + glBeginTransformFeedback@4 @213 + glEndTransformFeedback@0 @214 + glBindBufferRange@20 @215 + glBindBufferBase@12 @216 + glTransformFeedbackVaryings@16 @217 + glGetTransformFeedbackVarying@28 @218 + glVertexAttribIPointer@20 @219 + glGetVertexAttribIiv@12 @220 + glGetVertexAttribIuiv@12 @221 + glVertexAttribI4i@20 @222 + glVertexAttribI4ui@20 @223 + glVertexAttribI4iv@8 @224 + glVertexAttribI4uiv@8 @225 + glGetUniformuiv@12 @226 + glGetFragDataLocation@8 @227 + glUniform1ui@8 @228 + glUniform2ui@12 @229 + glUniform3ui@16 @230 + glUniform4ui@20 @231 + glUniform1uiv@12 @232 + glUniform2uiv@12 @233 + glUniform3uiv@12 @234 + glUniform4uiv@12 @235 + glClearBufferiv@12 @236 + glClearBufferuiv@12 @237 + glClearBufferfv@12 @238 + glClearBufferfi@16 @239 + glGetStringi@8 @240 + glCopyBufferSubData@20 @241 + glGetUniformIndices@16 @242 + glGetActiveUniformsiv@20 @243 + glGetUniformBlockIndex@8 @244 + glGetActiveUniformBlockiv@16 @245 + glGetActiveUniformBlockName@20 @246 + glUniformBlockBinding@12 @247 + glDrawArraysInstanced@16 @248 + glDrawElementsInstanced@20 @249 + glFenceSync@8 @250 + glIsSync@4 @251 + glDeleteSync@4 @252 + glClientWaitSync@16 @253 + glWaitSync@16 @254 + glGetInteger64v@8 @255 + glGetSynciv@20 @256 + glGetInteger64i_v@12 @257 + glGetBufferParameteri64v@12 @258 + glGenSamplers@8 @259 + glDeleteSamplers@8 @260 + glIsSampler@4 @261 + glBindSampler@8 @262 + glSamplerParameteri@12 @263 + glSamplerParameteriv@12 @264 + glSamplerParameterf@12 @265 + glSamplerParameterfv@12 @266 + glGetSamplerParameteriv@12 @267 + glGetSamplerParameterfv@12 @268 + glVertexAttribDivisor@8 @269 + glBindTransformFeedback@8 @270 + glDeleteTransformFeedbacks@8 @271 + glGenTransformFeedbacks@8 @272 + glIsTransformFeedback@4 @273 + glPauseTransformFeedback@0 @274 + glResumeTransformFeedback@0 @275 + glGetProgramBinary@20 @276 + glProgramBinary@16 @277 + glProgramParameteri@12 @278 + glInvalidateFramebuffer@12 @279 + glInvalidateSubFramebuffer@28 @280 + glTexStorage2D@20 @281 + glTexStorage3D@24 @282 + glGetInternalformativ@20 @283 - ; Setting up TRACE macro callbacks - SetTraceFunctionPointers@8 @180 + ; EGL dependencies + glCreateContext @144 NONAME + glDestroyContext @145 NONAME + glMakeCurrent @146 NONAME + glGetCurrentContext @147 NONAME + glGetProcAddress@4 @148 NONAME + glBindTexImage@4 @158 NONAME + glCreateRenderer @177 NONAME + glDestroyRenderer @178 NONAME + + ; Setting up TRACE macro callbacks + SetTraceFunctionPointers@8 @284 diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp index e52799438d..8820700c76 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.cpp +++ b/src/3rdparty/angle/src/libGLESv2/main.cpp @@ -8,60 +8,56 @@ // main.cpp: DLL entry point and management of thread-local data. #include "libGLESv2/main.h" - #include "libGLESv2/Context.h" -#if !defined(ANGLE_OS_WINRT) -static DWORD currentTLS = TLS_OUT_OF_INDEXES; -#else -static __declspec(thread) void *currentTLS = 0; +#include "common/tls.h" + +#if defined(ANGLE_PLATFORM_WINRT) +__declspec(thread) #endif +static TLSIndex currentTLS = TLS_OUT_OF_INDEXES; namespace gl { Current *AllocateCurrent() { -#if !defined(ANGLE_OS_WINRT) - Current *current = (Current*)LocalAlloc(LPTR, sizeof(Current)); -#else - currentTLS = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(Current)); - Current *current = (Current*)currentTLS; +#if defined(ANGLE_PLATFORM_WINRT) + if (currentTLS == TLS_OUT_OF_INDEXES) + { + currentTLS = CreateTLSIndex(); + } #endif - - if (!current) + ASSERT(currentTLS != TLS_OUT_OF_INDEXES); + if (currentTLS == TLS_OUT_OF_INDEXES) { - ERR("Could not allocate thread local storage."); return NULL; } -#if !defined(ANGLE_OS_WINRT) - ASSERT(currentTLS != TLS_OUT_OF_INDEXES); - TlsSetValue(currentTLS, current); -#endif - + Current *current = new Current(); current->context = NULL; current->display = NULL; + if (!SetTLSValue(currentTLS, current)) + { + ERR("Could not set thread local storage."); + return NULL; + } + return current; } void DeallocateCurrent() { -#if !defined(ANGLE_OS_WINRT) - void *current = TlsGetValue(currentTLS); - - if (current) +#if defined(ANGLE_PLATFORM_WINRT) + if (currentTLS == TLS_OUT_OF_INDEXES) { - LocalFree((HLOCAL)current); - } -#else - if (currentTLS) - { - HeapFree(GetProcessHeap(), 0, currentTLS); - currentTLS = 0; + return; } #endif + Current *current = reinterpret_cast(GetTLSValue(currentTLS)); + SafeDelete(current); + SetTLSValue(currentTLS, NULL); } } @@ -74,16 +70,16 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved { case DLL_PROCESS_ATTACH: { -#if !defined(ANGLE_OS_WINRT) - currentTLS = TlsAlloc(); - +#if defined(ANGLE_PLATFORM_WINRT) // On WinRT, don't handle TLS from DllMain + return DisableThreadLibraryCalls(instance); +#endif + currentTLS = CreateTLSIndex(); if (currentTLS == TLS_OUT_OF_INDEXES) { return FALSE; } -#endif } - // Fall throught to initialize index + // Fall through to initialize index case DLL_THREAD_ATTACH: { gl::AllocateCurrent(); @@ -96,9 +92,9 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved break; case DLL_PROCESS_DETACH: { +#if !defined(ANGLE_PLATFORM_WINRT) gl::DeallocateCurrent(); -#if !defined(ANGLE_OS_WINRT) - TlsFree(currentTLS); + DestroyTLSIndex(currentTLS); #endif } break; @@ -117,20 +113,16 @@ namespace gl Current *GetCurrentData() { #ifndef QT_OPENGL_ES_2_ANGLE_STATIC -#if !defined(ANGLE_OS_WINRT) - Current *current = (Current*)TlsGetValue(currentTLS); -#else - Current *current = (Current*)currentTLS; -#endif -#else - // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. - static Current s_current = { 0, 0 }; - Current *current = &s_current; -#endif + Current *current = reinterpret_cast(GetTLSValue(currentTLS)); // ANGLE issue 488: when the dll is loaded after thread initialization, // thread local storage (current) might not exist yet. return (current ? current : AllocateCurrent()); +#else + // No precautions for thread safety taken as ANGLE is used single-threaded in Qt. + static Current current = { 0, 0 }; + return ¤t; +#endif } void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface) @@ -156,7 +148,7 @@ Context *getContext() Context *getNonLostContext() { Context *context = getContext(); - + if (context) { if (context->isContextLost()) diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h index 69465c9bbf..df28ea400d 100644 --- a/src/3rdparty/angle/src/libGLESv2/main.h +++ b/src/3rdparty/angle/src/libGLESv2/main.h @@ -10,6 +10,13 @@ #define LIBGLESV2_MAIN_H_ #include "common/debug.h" +#undef EGLAPI +#define EGLAPI +#include + +#ifndef Sleep +#define Sleep(ms) WaitForSingleObjectEx(GetCurrentThread(), ms, FALSE) +#endif namespace egl { @@ -53,11 +60,11 @@ class Renderer; extern "C" { // Exported functions for use by EGL -gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); +gl::Context *glCreateContext(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess); void glDestroyContext(gl::Context *context); void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface); gl::Context *glGetCurrentContext(); -rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType displayId); +rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType); void glDestroyRenderer(rx::Renderer *renderer); __eglMustCastToProperFunctionPointerType __stdcall glGetProcAddress(const char *procname); diff --git a/src/3rdparty/angle/src/libGLESv2/mathutil.h b/src/3rdparty/angle/src/libGLESv2/mathutil.h deleted file mode 100644 index 6474b66745..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/mathutil.h +++ /dev/null @@ -1,162 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// mathutil.h: Math and bit manipulation functions. - -#ifndef LIBGLESV2_MATHUTIL_H_ -#define LIBGLESV2_MATHUTIL_H_ - -#include - -#include "common/debug.h" - -namespace gl -{ -struct Vector4 -{ - Vector4() {} - Vector4(float x, float y, float z, float w) : x(x), y(y), z(z), w(w) {} - - float x; - float y; - float z; - float w; -}; - -inline bool isPow2(int x) -{ - return (x & (x - 1)) == 0 && (x != 0); -} - -inline int log2(int x) -{ - int r = 0; - while ((x >> r) > 1) r++; - return r; -} - -inline unsigned int ceilPow2(unsigned int x) -{ - if (x != 0) x--; - x |= x >> 1; - x |= x >> 2; - x |= x >> 4; - x |= x >> 8; - x |= x >> 16; - x++; - - return x; -} - -template -inline T clamp(T x, MIN min, MAX max) -{ - // Since NaNs fail all comparison tests, a NaN value will default to min - return x > min ? (x > max ? max : x) : min; -} - -inline float clamp01(float x) -{ - return clamp(x, 0.0f, 1.0f); -} - -template -inline unsigned int unorm(float x) -{ - const unsigned int max = 0xFFFFFFFF >> (32 - n); - - if (x > 1) - { - return max; - } - else if (x < 0) - { - return 0; - } - else - { - return (unsigned int)(max * x + 0.5f); - } -} - -inline bool supportsSSE2() -{ - static bool checked = false; - static bool supports = false; - - if (checked) - { - return supports; - } - -#if defined(_M_IX86) || defined(_M_AMD64) // ARM doesn't provide __cpuid() - int info[4]; - __cpuid(info, 0); - - if (info[0] >= 1) - { - __cpuid(info, 1); - - supports = (info[3] >> 26) & 1; - } -#endif - - checked = true; - - return supports; -} - -inline unsigned short float32ToFloat16(float fp32) -{ - unsigned int fp32i = (unsigned int&)fp32; - unsigned int sign = (fp32i & 0x80000000) >> 16; - unsigned int abs = fp32i & 0x7FFFFFFF; - - if(abs > 0x47FFEFFF) // Infinity - { - return sign | 0x7FFF; - } - else if(abs < 0x38800000) // Denormal - { - unsigned int mantissa = (abs & 0x007FFFFF) | 0x00800000; - int e = 113 - (abs >> 23); - - if(e < 24) - { - abs = mantissa >> e; - } - else - { - abs = 0; - } - - return sign | (abs + 0x00000FFF + ((abs >> 13) & 1)) >> 13; - } - else - { - return sign | (abs + 0xC8000000 + 0x00000FFF + ((abs >> 13) & 1)) >> 13; - } -} - -float float16ToFloat32(unsigned short h); - -} - -namespace rx -{ - -struct Range -{ - Range() {} - Range(int lo, int hi) : start(lo), end(hi) { ASSERT(lo <= hi); } - - int start; - int end; -}; - -} - -#endif // LIBGLESV2_MATHUTIL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/precompiled.h b/src/3rdparty/angle/src/libGLESv2/precompiled.h index 2ff09f531e..0404eabf8a 100644 --- a/src/3rdparty/angle/src/libGLESv2/precompiled.h +++ b/src/3rdparty/angle/src/libGLESv2/precompiled.h @@ -6,16 +6,14 @@ // precompiled.h: Precompiled header file for libGLESv2. -#define GL_APICALL -#include -#include - -#define EGLAPI +#include "angle_gl.h" #include +#include #include #include #include +#include #include #include #include @@ -31,57 +29,4 @@ #include #include #include - -#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP) -# define ANGLE_OS_WINRT -# if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP -# define ANGLE_OS_WINPHONE -# endif -#endif - -#if defined(ANGLE_ENABLE_D3D9) -# include -#endif -#if defined(ANGLE_ENABLE_D3D11) -# if !defined(ANGLE_OS_WINRT) -# include -# else -# include -# define Sleep(x) WaitForSingleObjectEx(GetCurrentThread(), x, FALSE) -# define GetVersion() WINVER -# define LoadLibrary(x) LoadPackagedLibrary(x, NULL) -# endif -# include -#endif -#if !defined(ANGLE_OS_WINPHONE) -# include -#endif - -#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL0 -#define D3DCOMPILE_OPTIMIZATION_LEVEL0 (1 << 14) -#endif -#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL1 -#define D3DCOMPILE_OPTIMIZATION_LEVEL1 0 -#endif -#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL2 -#define D3DCOMPILE_OPTIMIZATION_LEVEL2 ((1 << 14) | (1 << 15)) -#endif -#ifndef D3DCOMPILE_OPTIMIZATION_LEVEL3 -#define D3DCOMPILE_OPTIMIZATION_LEVEL3 (1 << 15) -#endif -#ifndef D3DCOMPILE_DEBUG -#define D3DCOMPILE_DEBUG (1 << 0) -#endif -#ifndef D3DCOMPILE_SKIP_OPTIMIZATION -#define D3DCOMPILE_SKIP_OPTIMIZATION (1 << 2) -#endif -#ifndef D3DCOMPILE_AVOID_FLOW_CONTROL -#define D3DCOMPILE_AVOID_FLOW_CONTROL (1 << 9) -#endif -#ifndef D3DCOMPILE_PREFER_FLOW_CONTROL -#define D3DCOMPILE_PREFER_FLOW_CONTROL (1 << 10) -#endif - -#ifdef _MSC_VER -#include -#endif +#include diff --git a/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp b/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp new file mode 100644 index 0000000000..67578efe3a --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp @@ -0,0 +1,148 @@ +#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 +// found in the LICENSE file. +// + +// queryconversions.cpp: Implementation of state query cast conversions + +#include "libGLESv2/Context.h" +#include "common/utilities.h" + +namespace gl +{ + +// Helper class for converting a GL type to a GLenum: +// We can't use CastStateValueEnum generally, because of GLboolean + GLubyte overlap. +// We restrict our use to CastStateValue, where it eliminates duplicate parameters. + +template +struct CastStateValueEnum { static GLenum mEnumForType; }; + +template <> GLenum CastStateValueEnum::mEnumForType = GL_INT; +template <> GLenum CastStateValueEnum::mEnumForType = GL_UNSIGNED_INT; +template <> GLenum CastStateValueEnum::mEnumForType = GL_BOOL; +template <> GLenum CastStateValueEnum::mEnumForType = GL_INT_64_ANGLEX; +template <> GLenum CastStateValueEnum::mEnumForType = GL_FLOAT; + +template +QueryT CastStateValueToInt(GLenum pname, NativeT value) +{ + GLenum queryType = CastStateValueEnum::mEnumForType; + GLenum nativeType = CastStateValueEnum::mEnumForType; + + if (nativeType == GL_FLOAT) + { + // RGBA color values and DepthRangeF values are converted to integer using Equation 2.4 from Table 4.5 + if (pname == GL_DEPTH_RANGE || pname == GL_COLOR_CLEAR_VALUE || pname == GL_DEPTH_CLEAR_VALUE || pname == GL_BLEND_COLOR) + { + return static_cast((static_cast(0xFFFFFFFF) * value - 1.0f) / 2.0f); + } + else + { + return gl::iround(value); + } + } + + // Clamp 64-bit int values when casting to int + if (nativeType == GL_INT_64_ANGLEX && queryType == GL_INT) + { + GLint64 minIntValue = static_cast(std::numeric_limits::min()); + GLint64 maxIntValue = static_cast(std::numeric_limits::max()); + GLint64 clampedValue = std::max(std::min(static_cast(value), maxIntValue), minIntValue); + return static_cast(clampedValue); + } + + return static_cast(value); +} + +template +QueryT CastStateValue(GLenum pname, NativeT value) +{ + GLenum queryType = CastStateValueEnum::mEnumForType; + + switch (queryType) + { + case GL_INT: return CastStateValueToInt(pname, value); + case GL_INT_64_ANGLEX: return CastStateValueToInt(pname, value); + case GL_FLOAT: return static_cast(value); + case GL_BOOL: return (value == static_cast(0) ? GL_FALSE : GL_TRUE); + default: UNREACHABLE(); return 0; + } +} + +template +void CastStateValues(Context *context, GLenum nativeType, GLenum pname, + unsigned int numParams, QueryT *outParams) +{ + if (nativeType == GL_INT) + { + GLint *intParams = NULL; + intParams = new GLint[numParams]; + + context->getIntegerv(pname, intParams); + + for (unsigned int i = 0; i < numParams; ++i) + { + outParams[i] = CastStateValue(pname, intParams[i]); + } + + delete [] intParams; + } + else if (nativeType == GL_BOOL) + { + GLboolean *boolParams = NULL; + boolParams = new GLboolean[numParams]; + + context->getBooleanv(pname, boolParams); + + for (unsigned int i = 0; i < numParams; ++i) + { + outParams[i] = (boolParams[i] == GL_FALSE ? static_cast(0) : static_cast(1)); + } + + delete [] boolParams; + } + else if (nativeType == GL_FLOAT) + { + GLfloat *floatParams = NULL; + floatParams = new GLfloat[numParams]; + + context->getFloatv(pname, floatParams); + + for (unsigned int i = 0; i < numParams; ++i) + { + outParams[i] = CastStateValue(pname, floatParams[i]); + } + + delete [] floatParams; + } + else if (nativeType == GL_INT_64_ANGLEX) + { + GLint64 *int64Params = NULL; + int64Params = new GLint64[numParams]; + + context->getInteger64v(pname, int64Params); + + for (unsigned int i = 0; i < numParams; ++i) + { + outParams[i] = CastStateValue(pname, int64Params[i]); + } + + delete [] int64Params; + } + else UNREACHABLE(); +} + +// Explicit template instantiation (how we export template functions in different files) +// The calls below will make CastStateValues successfully link with the GL state query types +// The GL state query API types are: bool, int, uint, float, int64 + +template void CastStateValues(Context *, GLenum, GLenum, unsigned int, GLboolean *); +template void CastStateValues(Context *, GLenum, GLenum, unsigned int, GLint *); +template void CastStateValues(Context *, GLenum, GLenum, unsigned int, GLuint *); +template void CastStateValues(Context *, GLenum, GLenum, unsigned int, GLfloat *); +template void CastStateValues(Context *, GLenum, GLenum, unsigned int, GLint64 *); + +} diff --git a/src/3rdparty/angle/src/libGLESv2/queryconversions.h b/src/3rdparty/angle/src/libGLESv2/queryconversions.h new file mode 100644 index 0000000000..da7047f730 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/queryconversions.h @@ -0,0 +1,17 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// queryconversions.h: Declaration of state query cast conversions + +namespace gl +{ + +// The GL state query API types are: bool, int, uint, float, int64 +template +void CastStateValues(Context *context, GLenum nativeType, GLenum pname, + unsigned int numParams, QueryT *outParams); + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h new file mode 100644 index 0000000000..bea689b956 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h @@ -0,0 +1,34 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferImpl.h: Defines the abstract rx::BufferImpl class. + +#ifndef LIBGLESV2_RENDERER_BUFFERIMPL_H_ +#define LIBGLESV2_RENDERER_BUFFERIMPL_H_ + +#include "common/angleutils.h" +#include "libGLESv2/Buffer.h" + +namespace rx +{ + +class BufferImpl +{ + public: + virtual ~BufferImpl() { } + + virtual void 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 void markTransformFeedbackUsage() = 0; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFERIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.cpp deleted file mode 100644 index a49b7bab84..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BufferStorage.cpp Defines the abstract BufferStorage class. - -#include "libGLESv2/renderer/BufferStorage.h" - -namespace rx -{ - -unsigned int BufferStorage::mNextSerial = 1; - -BufferStorage::BufferStorage() -{ - updateSerial(); -} - -BufferStorage::~BufferStorage() -{ -} - -unsigned int BufferStorage::getSerial() const -{ - return mSerial; -} - -void BufferStorage::updateSerial() -{ - mSerial = mNextSerial++; -} - -void BufferStorage::markBufferUsage() -{ -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h deleted file mode 100644 index ace1a11bae..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferStorage.h +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BufferStorage.h Defines the abstract BufferStorage class. - -#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE_H_ -#define LIBGLESV2_RENDERER_BUFFERSTORAGE_H_ - -#include "common/angleutils.h" - -namespace rx -{ - -class BufferStorage -{ - public: - BufferStorage(); - virtual ~BufferStorage(); - - // The data returned is only guaranteed valid until next non-const method. - virtual void *getData() = 0; - virtual void setData(const void* data, unsigned int size, unsigned int offset) = 0; - virtual void clear() = 0; - virtual unsigned int getSize() const = 0; - virtual bool supportsDirectBinding() const = 0; - virtual void markBufferUsage(); - unsigned int getSerial() const; - - protected: - void updateSerial(); - - private: - DISALLOW_COPY_AND_ASSIGN(BufferStorage); - - unsigned int mSerial; - static unsigned int mNextSerial; -}; - -} - -#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h index d7f2102a2e..d54e6becd3 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h @@ -17,27 +17,16 @@ namespace rx class FenceImpl { public: - FenceImpl() : mStatus(GL_FALSE), mCondition(GL_NONE) { }; + FenceImpl() { }; virtual ~FenceImpl() { }; - virtual GLboolean isFence() = 0; - virtual void setFence(GLenum condition) = 0; - virtual GLboolean testFence() = 0; - virtual void finishFence() = 0; - virtual void getFenceiv(GLenum pname, GLint *params) = 0; - - protected: - void setStatus(GLboolean status) { mStatus = status; } - GLboolean getStatus() const { return mStatus; } - - void setCondition(GLuint condition) { mCondition = condition; } - GLuint getCondition() const { return mCondition; } + virtual bool isSet() const = 0; + virtual void set() = 0; + virtual bool test(bool flushCommandBuffer) = 0; + virtual bool hasError() const = 0; private: DISALLOW_COPY_AND_ASSIGN(FenceImpl); - - GLboolean mStatus; - GLenum mCondition; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp index 57239ef74f..5963534e03 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp @@ -18,531 +18,12 @@ Image::Image() { mWidth = 0; mHeight = 0; + mDepth = 0; mInternalFormat = GL_NONE; mActualFormat = GL_NONE; -} - -void Image::loadAlphaDataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = 0; - dest[4 * x + 1] = 0; - dest[4 * x + 2] = 0; - dest[4 * x + 3] = source[x]; - } - } -} - -void Image::loadAlphaDataToNative(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - memcpy(dest, source, width); - } -} - -void Image::loadAlphaFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = 0; - dest[4 * x + 1] = 0; - dest[4 * x + 2] = 0; - dest[4 * x + 3] = source[x]; - } - } -} - -void Image::loadAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = 0; - dest[4 * x + 1] = 0; - dest[4 * x + 2] = 0; - dest[4 * x + 3] = source[x]; - } - } -} - -void Image::loadLuminanceDataToNativeOrBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output, bool native) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - - if (!native) // BGRA8 destination format - { - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x]; - dest[4 * x + 1] = source[x]; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = 0xFF; - } - } - else // L8 destination format - { - memcpy(dest, source, width); - } - } -} - -void Image::loadLuminanceFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x]; - dest[4 * x + 1] = source[x]; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = 1.0f; - } - } -} - -void Image::loadLuminanceFloatDataToRGB(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[3 * x + 0] = source[x]; - dest[3 * x + 1] = source[x]; - dest[3 * x + 2] = source[x]; - } - } -} - -void Image::loadLuminanceHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x]; - dest[4 * x + 1] = source[x]; - dest[4 * x + 2] = source[x]; - dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1 - } - } -} - -void Image::loadLuminanceAlphaDataToNativeOrBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output, bool native) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - - if (!native) // BGRA8 destination format - { - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[2*x+0]; - dest[4 * x + 1] = source[2*x+0]; - dest[4 * x + 2] = source[2*x+0]; - dest[4 * x + 3] = source[2*x+1]; - } - } - else - { - memcpy(dest, source, width * 2); - } - } -} - -void Image::loadLuminanceAlphaFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[2*x+0]; - dest[4 * x + 1] = source[2*x+0]; - dest[4 * x + 2] = source[2*x+0]; - dest[4 * x + 3] = source[2*x+1]; - } - } -} - -void Image::loadLuminanceAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[2*x+0]; - dest[4 * x + 1] = source[2*x+0]; - dest[4 * x + 2] = source[2*x+0]; - dest[4 * x + 3] = source[2*x+1]; - } - } -} - -void Image::loadRGBUByteDataToBGRX(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x * 3 + 2]; - dest[4 * x + 1] = source[x * 3 + 1]; - dest[4 * x + 2] = source[x * 3 + 0]; - dest[4 * x + 3] = 0xFF; - } - } -} - -void Image::loadRGBUByteDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x * 3 + 0]; - dest[4 * x + 1] = source[x * 3 + 1]; - dest[4 * x + 2] = source[x * 3 + 2]; - dest[4 * x + 3] = 0xFF; - } - } -} - -void Image::loadRGB565DataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2); - dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9); - dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); - dest[4 * x + 3] = 0xFF; - } - } -} - -void Image::loadRGB565DataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); - dest[4 * x + 1] = ((rgba & 0x07E0) >> 3) | ((rgba & 0x07E0) >> 9); - dest[4 * x + 2] = ((rgba & 0x001F) << 3) | ((rgba & 0x001F) >> 2); - dest[4 * x + 3] = 0xFF; - } - } -} - -void Image::loadRGBFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x * 3 + 0]; - dest[4 * x + 1] = source[x * 3 + 1]; - dest[4 * x + 2] = source[x * 3 + 2]; - dest[4 * x + 3] = 1.0f; - } - } -} - -void Image::loadRGBFloatDataToNative(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - memcpy(dest, source, width * 12); - } -} - -void Image::loadRGBHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned short *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - for (int x = 0; x < width; x++) - { - dest[4 * x + 0] = source[x * 3 + 0]; - dest[4 * x + 1] = source[x * 3 + 1]; - dest[4 * x + 2] = source[x * 3 + 2]; - dest[4 * x + 3] = 0x3C00; // SEEEEEMMMMMMMMMM, S = 0, E = 15, M = 0: 16bit flpt representation of 1 - } - } -} - -void Image::loadRGBAUByteDataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned int *source = NULL; - unsigned int *dest = NULL; - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - - for (int x = 0; x < width; x++) - { - unsigned int rgba = source[x]; - dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); - } - } -} - -void Image::loadRGBAUByteDataToNative(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned int *source = NULL; - unsigned int *dest = NULL; - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - - memcpy(dest, source, width * 4); - } -} - -void Image::loadRGBA4444DataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); - dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); - dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); - dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); - } - } -} - -void Image::loadRGBA4444DataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); - dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); - dest[4 * x + 2] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); - dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); - } - } -} - -void Image::loadRGBA5551DataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); - dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); - dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); - dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; - } - } -} - -void Image::loadRGBA5551DataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned short *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = static_cast(output) + y * outputPitch; - for (int x = 0; x < width; x++) - { - unsigned short rgba = source[x]; - dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); - dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); - dest[4 * x + 2] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); - dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; - } - } -} - -void Image::loadRGBAFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const float *source = NULL; - float *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - memcpy(dest, source, width * 16); - } -} - -void Image::loadRGBAHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - memcpy(dest, source, width * 8); - } -} - -void Image::loadBGRADataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned char *source = NULL; - unsigned char *dest = NULL; - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = static_cast(output) + y * outputPitch; - memcpy(dest, source, width*4); - } + mTarget = GL_NONE; + mRenderable = false; + mDirty = false; } } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h b/src/3rdparty/angle/src/libGLESv2/renderer/Image.h index 454e83e21e..8fcffa4309 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Image.h @@ -20,9 +20,8 @@ class Framebuffer; namespace rx { + class Renderer; -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; class Image { @@ -32,93 +31,33 @@ class Image GLsizei getWidth() const { return mWidth; } GLsizei getHeight() const { return mHeight; } + GLsizei getDepth() const { return mDepth; } GLenum getInternalFormat() const { return mInternalFormat; } GLenum getActualFormat() const { return mActualFormat; } + GLenum getTarget() const { return mTarget; } + bool isRenderableFormat() const { return mRenderable; } void markDirty() {mDirty = true;} void markClean() {mDirty = false;} virtual bool isDirty() const = 0; - virtual void setManagedSurface(TextureStorageInterface2D *storage, int level) {}; - virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level) {}; - virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; - virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) = 0; - - virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) = 0; + virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) = 0; - virtual bool isRenderableFormat() const = 0; - - virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input) = 0; - virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, + virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLint unpackAlignment, GLenum type, const void *input) = 0; + virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, const void *input) = 0; - virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; - - static void loadAlphaDataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadAlphaDataToNative(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadAlphaDataToBGRASSE2(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadAlphaFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadLuminanceDataToNativeOrBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output, bool native); - static void loadLuminanceFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadLuminanceFloatDataToRGB(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadLuminanceHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadLuminanceAlphaDataToNativeOrBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output, bool native); - static void loadLuminanceAlphaFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadLuminanceAlphaHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBUByteDataToBGRX(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBUByteDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGB565DataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGB565DataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBFloatDataToNative(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBAUByteDataToBGRASSE2(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBAUByteDataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBAUByteDataToNative(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBA4444DataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBA4444DataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBA5551DataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBA5551DataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBAFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadRGBAHalfFloatDataToRGBA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); - static void loadBGRADataToBGRA(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output); + virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0; protected: GLsizei mWidth; GLsizei mHeight; - GLint mInternalFormat; + GLsizei mDepth; + GLenum mInternalFormat; GLenum mActualFormat; + bool mRenderable; + GLenum mTarget; bool mDirty; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ImageSSE2.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/ImageSSE2.cpp deleted file mode 100644 index b2a90ca961..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ImageSSE2.cpp +++ /dev/null @@ -1,100 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ImageSSE2.cpp: Implements SSE2-based functions of rx::Image class. It's -// in a separated file for GCC, which can enable SSE usage only per-file, -// not for code blocks that use SSE2 explicitly. - -#include "libGLESv2/Texture.h" -#include "libGLESv2/renderer/Image.h" - -namespace rx -{ - -void Image::loadRGBAUByteDataToBGRASSE2(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned int *source = NULL; - unsigned int *dest = NULL; - __m128i brMask = _mm_set1_epi32(0x00ff00ff); - - for (int y = 0; y < height; y++) - { - source = reinterpret_cast(static_cast(input) + y * inputPitch); - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - int x = 0; - - // Make output writes aligned - for (x = 0; ((reinterpret_cast(&dest[x]) & 15) != 0) && x < width; x++) - { - unsigned int rgba = source[x]; - dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); - } - - for (; x + 3 < width; x += 4) - { - __m128i sourceData = _mm_loadu_si128(reinterpret_cast(&source[x])); - // Mask out g and a, which don't change - __m128i gaComponents = _mm_andnot_si128(brMask, sourceData); - // Mask out b and r - __m128i brComponents = _mm_and_si128(sourceData, brMask); - // Swap b and r - __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1)); - __m128i result = _mm_or_si128(gaComponents, brSwapped); - _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result); - } - - // Perform leftover writes - for (; x < width; x++) - { - unsigned int rgba = source[x]; - dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); - } - } -} - -void Image::loadAlphaDataToBGRASSE2(GLsizei width, GLsizei height, - int inputPitch, const void *input, size_t outputPitch, void *output) -{ - const unsigned char *source = NULL; - unsigned int *dest = NULL; - __m128i zeroWide = _mm_setzero_si128(); - - for (int y = 0; y < height; y++) - { - source = static_cast(input) + y * inputPitch; - dest = reinterpret_cast(static_cast(output) + y * outputPitch); - - int x; - // Make output writes aligned - for (x = 0; ((reinterpret_cast(&dest[x]) & 0xF) != 0 && x < width); x++) - { - dest[x] = static_cast(source[x]) << 24; - } - - for (; x + 7 < width; x += 8) - { - __m128i sourceData = _mm_loadl_epi64(reinterpret_cast(&source[x])); - // Interleave each byte to 16bit, make the lower byte to zero - sourceData = _mm_unpacklo_epi8(zeroWide, sourceData); - // Interleave each 16bit to 32bit, make the lower 16bit to zero - __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData); - __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData); - - _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo); - _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi); - } - - // Handle the remainder - for (; x < width; x++) - { - dest[x] = static_cast(source[x]) << 24; - } - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp deleted file mode 100644 index 37dbd3e195..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.cpp +++ /dev/null @@ -1,197 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface -// class with derivations, classes that perform graphics API agnostic index buffer operations. - -#include "libGLESv2/renderer/IndexBuffer.h" -#include "libGLESv2/renderer/Renderer.h" - -namespace rx -{ - -unsigned int IndexBuffer::mNextSerial = 1; - -IndexBuffer::IndexBuffer() -{ - updateSerial(); -} - -IndexBuffer::~IndexBuffer() -{ -} - -unsigned int IndexBuffer::getSerial() const -{ - return mSerial; -} - -void IndexBuffer::updateSerial() -{ - mSerial = mNextSerial++; -} - - -IndexBufferInterface::IndexBufferInterface(Renderer *renderer, bool dynamic) : mRenderer(renderer) -{ - mIndexBuffer = renderer->createIndexBuffer(); - - mDynamic = dynamic; - mWritePosition = 0; -} - -IndexBufferInterface::~IndexBufferInterface() -{ - if (mIndexBuffer) - { - delete mIndexBuffer; - } -} - -GLenum IndexBufferInterface::getIndexType() const -{ - return mIndexBuffer->getIndexType(); -} - -unsigned int IndexBufferInterface::getBufferSize() const -{ - return mIndexBuffer->getBufferSize(); -} - -unsigned int IndexBufferInterface::getSerial() const -{ - return mIndexBuffer->getSerial(); -} - -bool IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset) -{ - // Protect against integer overflow - if (mWritePosition + size < mWritePosition) - { - return false; - } - - if (!mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory)) - { - if (outMappedMemory) - { - *outMappedMemory = NULL; - } - return false; - } - - if (streamOffset) - { - *streamOffset = mWritePosition; - } - - mWritePosition += size; - return true; -} - -bool IndexBufferInterface::unmapBuffer() -{ - return mIndexBuffer->unmapBuffer(); -} - -IndexBuffer * IndexBufferInterface::getIndexBuffer() const -{ - return mIndexBuffer; -} - -unsigned int IndexBufferInterface::getWritePosition() const -{ - return mWritePosition; -} - -void IndexBufferInterface::setWritePosition(unsigned int writePosition) -{ - mWritePosition = writePosition; -} - -bool IndexBufferInterface::discard() -{ - return mIndexBuffer->discard(); -} - -bool IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType) -{ - if (mIndexBuffer->getBufferSize() == 0) - { - return mIndexBuffer->initialize(bufferSize, indexType, mDynamic); - } - else - { - return mIndexBuffer->setSize(bufferSize, indexType); - } -} - -StreamingIndexBufferInterface::StreamingIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, true) -{ -} - -StreamingIndexBufferInterface::~StreamingIndexBufferInterface() -{ -} - -bool StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType) -{ - bool result = true; - unsigned int curBufferSize = getBufferSize(); - unsigned int writePos = getWritePosition(); - if (size > curBufferSize) - { - result = setBufferSize(std::max(size, 2 * curBufferSize), indexType); - setWritePosition(0); - } - else if (writePos + size > curBufferSize || writePos + size < writePos) - { - if (!discard()) - { - return false; - } - setWritePosition(0); - } - - return result; -} - - -StaticIndexBufferInterface::StaticIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, false) -{ -} - -StaticIndexBufferInterface::~StaticIndexBufferInterface() -{ -} - -bool StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType) -{ - unsigned int curSize = getBufferSize(); - if (curSize == 0) - { - return setBufferSize(size, indexType); - } - else if (curSize >= size && indexType == getIndexType()) - { - return true; - } - else - { - ERR("Static index buffers can't be resized"); - UNREACHABLE(); - return false; - } -} - -IndexRangeCache *StaticIndexBufferInterface::getIndexRangeCache() -{ - return &mIndexRangeCache; -} - -} - diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h deleted file mode 100644 index 6fb885a1cd..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexBuffer.h +++ /dev/null @@ -1,111 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexBuffer.h: Defines the abstract IndexBuffer class and IndexBufferInterface -// class with derivations, classes that perform graphics API agnostic index buffer operations. - -#ifndef LIBGLESV2_RENDERER_INDEXBUFFER_H_ -#define LIBGLESV2_RENDERER_INDEXBUFFER_H_ - -#include "common/angleutils.h" -#include "libGLESv2/renderer/IndexRangeCache.h" - -namespace rx -{ -class Renderer; - -class IndexBuffer -{ - public: - IndexBuffer(); - virtual ~IndexBuffer(); - - virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) = 0; - - virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) = 0; - virtual bool unmapBuffer() = 0; - - virtual bool discard() = 0; - - virtual GLenum getIndexType() const = 0; - virtual unsigned int getBufferSize() const = 0; - virtual bool setSize(unsigned int bufferSize, GLenum indexType) = 0; - - unsigned int getSerial() const; - - protected: - void updateSerial(); - - private: - DISALLOW_COPY_AND_ASSIGN(IndexBuffer); - - unsigned int mSerial; - static unsigned int mNextSerial; -}; - -class IndexBufferInterface -{ - public: - IndexBufferInterface(Renderer *renderer, bool dynamic); - virtual ~IndexBufferInterface(); - - virtual bool reserveBufferSpace(unsigned int size, GLenum indexType) = 0; - - GLenum getIndexType() const; - unsigned int getBufferSize() const; - - unsigned int getSerial() const; - - bool mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset); - bool unmapBuffer(); - - IndexBuffer *getIndexBuffer() const; - - protected: - unsigned int getWritePosition() const; - void setWritePosition(unsigned int writePosition); - - bool discard(); - - bool setBufferSize(unsigned int bufferSize, GLenum indexType); - - private: - DISALLOW_COPY_AND_ASSIGN(IndexBufferInterface); - - rx::Renderer *const mRenderer; - - IndexBuffer* mIndexBuffer; - - unsigned int mWritePosition; - bool mDynamic; -}; - -class StreamingIndexBufferInterface : public IndexBufferInterface -{ - public: - StreamingIndexBufferInterface(Renderer *renderer); - ~StreamingIndexBufferInterface(); - - virtual bool reserveBufferSpace(unsigned int size, GLenum indexType); -}; - -class StaticIndexBufferInterface : public IndexBufferInterface -{ - public: - explicit StaticIndexBufferInterface(Renderer *renderer); - ~StaticIndexBufferInterface(); - - virtual bool reserveBufferSpace(unsigned int size, GLenum indexType); - - IndexRangeCache *getIndexRangeCache(); - - private: - IndexRangeCache mIndexRangeCache; -}; - -} - -#endif // LIBGLESV2_RENDERER_INDEXBUFFER_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp deleted file mode 100644 index 49bace8193..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.cpp +++ /dev/null @@ -1,339 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexDataManager.cpp: Defines the IndexDataManager, a class that -// runs the Buffer translation process for index buffers. - -#include "libGLESv2/renderer/IndexDataManager.h" -#include "libGLESv2/renderer/BufferStorage.h" - -#include "libGLESv2/Buffer.h" -#include "libGLESv2/main.h" -#include "libGLESv2/utilities.h" -#include "libGLESv2/renderer/IndexBuffer.h" - -namespace rx -{ - -IndexDataManager::IndexDataManager(Renderer *renderer) : mRenderer(renderer) -{ - mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer); - if (!mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT)) - { - delete mStreamingBufferShort; - mStreamingBufferShort = NULL; - } - - mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer); - if (!mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) - { - delete mStreamingBufferInt; - mStreamingBufferInt = NULL; - } - - if (!mStreamingBufferShort) - { - // Make sure both buffers are deleted. - delete mStreamingBufferInt; - mStreamingBufferInt = NULL; - - ERR("Failed to allocate the streaming index buffer(s)."); - } - - mCountingBuffer = NULL; -} - -IndexDataManager::~IndexDataManager() -{ - delete mStreamingBufferShort; - delete mStreamingBufferInt; - delete mCountingBuffer; -} - -static void convertIndices(GLenum type, const void *input, GLsizei count, void *output) -{ - if (type == GL_UNSIGNED_BYTE) - { - const GLubyte *in = static_cast(input); - GLushort *out = static_cast(output); - - for (GLsizei i = 0; i < count; i++) - { - out[i] = in[i]; - } - } - else if (type == GL_UNSIGNED_INT) - { - memcpy(output, input, count * sizeof(GLuint)); - } - else if (type == GL_UNSIGNED_SHORT) - { - memcpy(output, input, count * sizeof(GLushort)); - } - else UNREACHABLE(); -} - -template -static void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) -{ - *minIndex = indices[0]; - *maxIndex = indices[0]; - - for (GLsizei i = 0; i < count; i++) - { - if (*minIndex > indices[i]) *minIndex = indices[i]; - if (*maxIndex < indices[i]) *maxIndex = indices[i]; - } -} - -static void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) -{ - if (type == GL_UNSIGNED_BYTE) - { - computeRange(static_cast(indices), count, minIndex, maxIndex); - } - else if (type == GL_UNSIGNED_INT) - { - computeRange(static_cast(indices), count, minIndex, maxIndex); - } - else if (type == GL_UNSIGNED_SHORT) - { - computeRange(static_cast(indices), count, minIndex, maxIndex); - } - else UNREACHABLE(); -} - -GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated) -{ - if (!mStreamingBufferShort) - { - return GL_OUT_OF_MEMORY; - } - - GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; - unsigned int offset = 0; - bool alignedOffset = false; - - BufferStorage *storage = NULL; - - if (buffer != NULL) - { - if (reinterpret_cast(indices) > std::numeric_limits::max()) - { - return GL_OUT_OF_MEMORY; - } - offset = static_cast(reinterpret_cast(indices)); - - storage = buffer->getStorage(); - - switch (type) - { - case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break; - case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break; - case GL_UNSIGNED_INT: alignedOffset = (offset % sizeof(GLuint) == 0); break; - default: UNREACHABLE(); alignedOffset = false; - } - - unsigned int typeSize = gl::ComputeTypeSize(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; - } - - indices = static_cast(storage->getData()) + offset; - } - - StreamingIndexBufferInterface *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort; - - StaticIndexBufferInterface *staticBuffer = buffer ? buffer->getStaticIndexBuffer() : NULL; - IndexBufferInterface *indexBuffer = streamingBuffer; - bool directStorage = alignedOffset && storage && storage->supportsDirectBinding() && - destinationIndexType == type; - unsigned int streamOffset = 0; - - if (directStorage) - { - indexBuffer = streamingBuffer; - streamOffset = offset; - storage->markBufferUsage(); - - if (!buffer->getIndexRangeCache()->findRange(type, offset, count, &translated->minIndex, - &translated->maxIndex, NULL)) - { - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - buffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, - translated->maxIndex, 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)) - { - streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType); - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, - translated->maxIndex, streamOffset); - } - } - else - { - unsigned int convertCount = count; - - if (staticBuffer) - { - if (staticBuffer->getBufferSize() == 0 && alignedOffset) - { - indexBuffer = staticBuffer; - convertCount = storage->getSize() / gl::ComputeTypeSize(type); - } - else - { - buffer->invalidateStaticData(); - staticBuffer = NULL; - } - } - - if (!indexBuffer) - { - ERR("No valid index buffer."); - return GL_INVALID_OPERATION; - } - - unsigned int indexTypeSize = gl::ComputeTypeSize(destinationIndexType); - if (convertCount > std::numeric_limits::max() / indexTypeSize) - { - ERR("Reserving %u indicies of %u bytes each exceeds the maximum buffer size.", convertCount, indexTypeSize); - return GL_OUT_OF_MEMORY; - } - - unsigned int bufferSizeRequired = convertCount * indexTypeSize; - if (!indexBuffer->reserveBufferSpace(bufferSizeRequired, type)) - { - ERR("Failed to reserve %u bytes in an index buffer.", bufferSizeRequired); - return GL_OUT_OF_MEMORY; - } - - void* output = NULL; - if (!indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset)) - { - ERR("Failed to map index buffer."); - return GL_OUT_OF_MEMORY; - } - - convertIndices(type, staticBuffer ? storage->getData() : indices, convertCount, output); - - if (!indexBuffer->unmapBuffer()) - { - ERR("Failed to unmap index buffer."); - return GL_OUT_OF_MEMORY; - } - - computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); - - if (staticBuffer) - { - streamOffset = (offset / gl::ComputeTypeSize(type)) * gl::ComputeTypeSize(destinationIndexType); - staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, - translated->maxIndex, streamOffset); - } - } - - translated->storage = directStorage ? storage : NULL; - translated->indexBuffer = indexBuffer->getIndexBuffer(); - translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial(); - translated->startIndex = streamOffset / gl::ComputeTypeSize(destinationIndexType); - translated->startOffset = streamOffset; - - if (buffer) - { - buffer->promoteStaticUsage(count * gl::ComputeTypeSize(type)); - } - - return GL_NO_ERROR; -} - -StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count) -{ - if (count <= 65536) // 16-bit indices - { - const unsigned int spaceNeeded = count * sizeof(unsigned short); - - if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded) - { - delete mCountingBuffer; - mCountingBuffer = new StaticIndexBufferInterface(mRenderer); - mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); - - void* mappedMemory = NULL; - if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL)) - { - ERR("Failed to map counting buffer."); - return NULL; - } - - unsigned short *data = reinterpret_cast(mappedMemory); - for(int i = 0; i < count; i++) - { - data[i] = i; - } - - if (!mCountingBuffer->unmapBuffer()) - { - ERR("Failed to unmap counting buffer."); - return NULL; - } - } - } - else if (mStreamingBufferInt) // 32-bit indices supported - { - const unsigned int spaceNeeded = count * sizeof(unsigned int); - - if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded) - { - delete mCountingBuffer; - mCountingBuffer = new StaticIndexBufferInterface(mRenderer); - mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); - - void* mappedMemory = NULL; - if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL)) - { - ERR("Failed to map counting buffer."); - return NULL; - } - - unsigned int *data = reinterpret_cast(mappedMemory); - for(int i = 0; i < count; i++) - { - data[i] = i; - } - - if (!mCountingBuffer->unmapBuffer()) - { - ERR("Failed to unmap counting buffer."); - return NULL; - } - } - } - else - { - return NULL; - } - - return mCountingBuffer; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.h deleted file mode 100644 index 0e77c81d1b..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexDataManager.h +++ /dev/null @@ -1,66 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexDataManager.h: Defines the IndexDataManager, a class that -// runs the Buffer translation process for index buffers. - -#ifndef LIBGLESV2_INDEXDATAMANAGER_H_ -#define LIBGLESV2_INDEXDATAMANAGER_H_ - -#include "common/angleutils.h" - -namespace -{ - enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) }; -} - -namespace gl -{ -class Buffer; -} - -namespace rx -{ -class StaticIndexBufferInterface; -class StreamingIndexBufferInterface; -class IndexBuffer; -class BufferStorage; -class Renderer; - -struct TranslatedIndexData -{ - unsigned int minIndex; - unsigned int maxIndex; - unsigned int startIndex; - unsigned int startOffset; // In bytes - - IndexBuffer *indexBuffer; - BufferStorage *storage; - unsigned int serial; -}; - -class IndexDataManager -{ - public: - explicit IndexDataManager(Renderer *renderer); - virtual ~IndexDataManager(); - - GLenum prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated); - StaticIndexBufferInterface *getCountingIndices(GLsizei count); - - private: - DISALLOW_COPY_AND_ASSIGN(IndexDataManager); - - Renderer *const mRenderer; - - StreamingIndexBufferInterface *mStreamingBufferShort; - StreamingIndexBufferInterface *mStreamingBufferInt; - StaticIndexBufferInterface *mCountingBuffer; -}; - -} - -#endif // LIBGLESV2_INDEXDATAMANAGER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp index 51d7f0b653..e957d96270 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp @@ -9,8 +9,8 @@ // ranges of indices. #include "libGLESv2/renderer/IndexRangeCache.h" +#include "libGLESv2/formatutils.h" #include "common/debug.h" -#include "libGLESv2/utilities.h" #include namespace rx @@ -31,7 +31,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::ComputeTypeSize(i->first.type) * i->first.count); + unsigned int rangeEnd = i->second.streamOffset + (gl::GetTypeBytes(i->first.type) * i->first.count); if (invalidateEnd < rangeStart || invalidateStart > rangeEnd) { diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h index 56834306f2..837a44acd3 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h @@ -11,6 +11,7 @@ #define LIBGLESV2_RENDERER_INDEXRANGECACHE_H_ #include "common/angleutils.h" +#include namespace rx { @@ -55,4 +56,4 @@ class IndexRangeCache } -#endif LIBGLESV2_RENDERER_INDEXRANGECACHE_H +#endif // LIBGLESV2_RENDERER_INDEXRANGECACHE_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h index a874047b0c..a6750a204b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h @@ -24,6 +24,7 @@ class QueryImpl virtual void end() = 0; virtual GLuint getResult() = 0; virtual GLboolean isResultAvailable() = 0; + virtual bool isStarted() const = 0; GLenum getType() const { return mType; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h index 80de39f4f7..44637ec7de 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h @@ -11,6 +11,7 @@ #define LIBGLESV2_RENDERER_RENDERTARGET_H_ #include "common/angleutils.h" +#include "libGLESv2/angletypes.h" namespace rx { @@ -21,6 +22,7 @@ class RenderTarget { mWidth = 0; mHeight = 0; + mDepth = 0; mInternalFormat = GL_NONE; mActualFormat = GL_NONE; mSamples = 0; @@ -28,21 +30,27 @@ class RenderTarget virtual ~RenderTarget() {}; - GLsizei getWidth() { return mWidth; } - GLsizei getHeight() { return mHeight; } - GLenum getInternalFormat() { return mInternalFormat; } - GLenum getActualFormat() { return mActualFormat; } - GLsizei getSamples() { return mSamples; } - + GLsizei getWidth() const { return mWidth; } + GLsizei getHeight() const { return mHeight; } + GLsizei getDepth() const { return mDepth; } + GLenum getInternalFormat() const { return mInternalFormat; } + GLenum getActualFormat() const { return mActualFormat; } + GLsizei getSamples() const { return mSamples; } + gl::Extents getExtents() const { return gl::Extents(mWidth, mHeight, mDepth); } + + virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) = 0; + struct Desc { GLsizei width; GLsizei height; + GLsizei depth; GLenum format; }; protected: GLsizei mWidth; GLsizei mHeight; + GLsizei mDepth; GLenum mInternalFormat; GLenum mActualFormat; GLsizei mSamples; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp index 5278113811..590004ac9b 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp @@ -1,6 +1,6 @@ #include "precompiled.h" // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -11,212 +11,77 @@ #include "libGLESv2/main.h" #include "libGLESv2/Program.h" #include "libGLESv2/renderer/Renderer.h" -#if defined(ANGLE_ENABLE_D3D9) -# include "libGLESv2/renderer/d3d9/Renderer9.h" -#endif -#if defined(ANGLE_ENABLE_D3D11) -# include "libGLESv2/renderer/d3d11/Renderer11.h" -#endif -#include "libGLESv2/utilities.h" +#include "common/utilities.h" #include "third_party/trace_event/trace_event.h" +#include "libGLESv2/Shader.h" -#ifndef D3DERR_OUTOFVIDEOMEMORY -#define D3DERR_OUTOFVIDEOMEMORY MAKE_HRESULT(1, 0x876, 380) -#endif - -#if defined(__MINGW32__) || defined(ANGLE_OS_WINPHONE) - -#ifndef D3DCOMPILER_DLL - -// Add define + typedefs for older MinGW-w64 headers (pre 5783) - -#define D3DCOMPILER_DLL L"d3dcompiler_43.dll" - -HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename, - const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, - const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); -typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const char *filename, - const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, - const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); - -#endif // D3DCOMPILER_DLL +#if defined (ANGLE_ENABLE_D3D9) +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#endif // ANGLE_ENABLE_D3D9 -#endif // __MINGW32__ || ANGLE_OS_WINPHONE +#if defined (ANGLE_ENABLE_D3D11) +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#endif // ANGLE_ENABLE_D3D11 -#ifndef QT_D3DCOMPILER_DLL -#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL +#if !defined(ANGLE_DEFAULT_D3D11) +// Enables use of the Direct3D 11 API for a default display, when available +#define ANGLE_DEFAULT_D3D11 0 #endif namespace rx { -Renderer::Renderer(egl::Display *display) : mDisplay(display) +Renderer::Renderer(egl::Display *display) + : mDisplay(display), + mCapsInitialized(false), + mCurrentClientVersion(2) { - mD3dCompilerModule = NULL; - mD3DCompileFunc = NULL; } Renderer::~Renderer() { - if (mD3dCompilerModule) - { - FreeLibrary(mD3dCompilerModule); - mD3dCompilerModule = NULL; - } + gl::Shader::releaseCompiler(); } -bool Renderer::initializeCompiler() +const gl::Caps &Renderer::getRendererCaps() const { - TRACE_EVENT0("gpu", "initializeCompiler"); -#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES) - // Find a D3DCompiler module that had already been loaded based on a predefined list of versions. - static TCHAR* d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES; - - for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i) + if (!mCapsInitialized) { - if (GetModuleHandleEx(0, d3dCompilerNames[i], &mD3dCompilerModule)) - { - break; - } + generateCaps(&mCaps, &mTextureCaps, &mExtensions); + mCapsInitialized = true; } -#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES - - // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL -#if !defined(ANGLE_OS_WINRT) - const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL"); - if (!defaultCompiler) - defaultCompiler = QT_D3DCOMPILER_DLL; -#else // !ANGLE_OS_WINRT -# ifdef _DEBUG - const wchar_t *defaultCompiler = L"d3dcompiler_qtd.dll"; -# else - const wchar_t *defaultCompiler = L"d3dcompiler_qt.dll"; -# endif -#endif // ANGLE_OS_WINRT - - const wchar_t *compilerDlls[] = { - defaultCompiler, - L"d3dcompiler_47.dll", - L"d3dcompiler_46.dll", - L"d3dcompiler_45.dll", - L"d3dcompiler_44.dll", - L"d3dcompiler_43.dll", - 0 - }; - // Load the first available known compiler DLL - for (int i = 0; compilerDlls[i]; ++i) - { - // Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with. - mD3dCompilerModule = LoadLibrary(compilerDlls[i]); - if (mD3dCompilerModule) - break; - } - - if (!mD3dCompilerModule) - { - ERR("No D3D compiler module found - aborting!\n"); - return false; - } - - mD3DCompileFunc = reinterpret_cast(GetProcAddress(mD3dCompilerModule, "D3DCompile")); - ASSERT(mD3DCompileFunc); - - return mD3DCompileFunc != NULL; + return mCaps; } -// Compiles HLSL code into executable binaries -ShaderBlob *Renderer::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags) +const gl::TextureCapsMap &Renderer::getRendererTextureCaps() const { - if (!hlsl) + if (!mCapsInitialized) { - return NULL; + generateCaps(&mCaps, &mTextureCaps, &mExtensions); + mCapsInitialized = true; } - HRESULT result = S_OK; - UINT flags = 0; - std::string sourceText; - if (gl::perfActive()) - { - flags |= D3DCOMPILE_DEBUG; - -#ifdef NDEBUG - flags |= optimizationFlags; -#else - flags |= D3DCOMPILE_SKIP_OPTIMIZATION; -#endif + return mTextureCaps; +} - std::string sourcePath = getTempPath(); - sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(hlsl); - writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); - } - else +const gl::Extensions &Renderer::getRendererExtensions() const +{ + if (!mCapsInitialized) { - flags |= optimizationFlags; - sourceText = hlsl; + generateCaps(&mCaps, &mTextureCaps, &mExtensions); + mCapsInitialized = true; } - // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. - // Try the default flags first and if compilation fails, try some alternatives. - const static UINT extraFlags[] = - { - 0, - D3DCOMPILE_AVOID_FLOW_CONTROL, - D3DCOMPILE_PREFER_FLOW_CONTROL - }; - - const static char * const extraFlagNames[] = - { - "default", - "avoid flow control", - "prefer flow control" - }; - - int attempts = alternateFlags ? ArraySize(extraFlags) : 1; - pD3DCompile compileFunc = reinterpret_cast(mD3DCompileFunc); - for (int i = 0; i < attempts; ++i) - { - ID3DBlob *errorMessage = NULL; - ID3DBlob *binary = NULL; - - result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL, - "main", profile, flags | extraFlags[i], 0, &binary, &errorMessage); - if (errorMessage) - { - const char *message = (const char*)errorMessage->GetBufferPointer(); - - infoLog.appendSanitized(message); - TRACE("\n%s", hlsl); - TRACE("\n%s", message); - - errorMessage->Release(); - errorMessage = NULL; - } - - if (SUCCEEDED(result)) - { - return (ShaderBlob*)binary; - } - else - { - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*) NULL); - } + return mExtensions; +} - infoLog.append("Warning: D3D shader compilation failed with "); - infoLog.append(extraFlagNames[i]); - infoLog.append(" flags."); - if (i + 1 < attempts) - { - infoLog.append(" Retrying with "); - infoLog.append(extraFlagNames[i + 1]); - infoLog.append(".\n"); - } - } - } +typedef Renderer *(*CreateRendererFunction)(egl::Display*, EGLNativeDisplayType, EGLint); - return NULL; +template +Renderer *CreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType) +{ + return new RendererType(display, nativeDisplay, requestedDisplayType); } } @@ -224,56 +89,64 @@ ShaderBlob *Renderer::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, co extern "C" { -rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType displayId) +rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, EGLint requestedDisplayType) { - rx::Renderer *renderer = NULL; - EGLint status = EGL_BAD_ALLOC; - -#if defined(ANGLE_OS_WINRT) - if (displayId == EGL_DEFAULT_DISPLAY) - displayId = EGL_D3D11_ONLY_DISPLAY_ANGLE; -#endif - -#if defined(ANGLE_ENABLE_D3D11) - if (displayId == EGL_DEFAULT_DISPLAY || - displayId == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || - displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) - { - renderer = new rx::Renderer11(display); + std::vector rendererCreationFunctions; - if (renderer) +# if defined(ANGLE_ENABLE_D3D11) + if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE) { - status = renderer->initialize(); + rendererCreationFunctions.push_back(rx::CreateRenderer); } +# endif - if (status == EGL_SUCCESS) +# if defined(ANGLE_ENABLE_D3D9) + if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE || + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE) { - return renderer; + rendererCreationFunctions.push_back(rx::CreateRenderer); } - else if (displayId == EGL_D3D11_ONLY_DISPLAY_ANGLE) - { - return NULL; - } - - // Failed to create a D3D11 renderer, try creating a D3D9 renderer - delete renderer; - } -#endif // ANGLE_ENABLE_D3D11 +# endif -#if defined(ANGLE_ENABLE_D3D9) - bool softwareDevice = (displayId == EGL_SOFTWARE_DISPLAY_ANGLE); - renderer = new rx::Renderer9(display, displayId, softwareDevice); - - if (renderer) + if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE && + nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE && + requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE) { - status = renderer->initialize(); + // The default display is requested, try the D3D9 and D3D11 renderers, order them using + // the definition of ANGLE_DEFAULT_D3D11 +# if ANGLE_DEFAULT_D3D11 +# if defined(ANGLE_ENABLE_D3D11) + rendererCreationFunctions.push_back(rx::CreateRenderer); +# endif +# if defined(ANGLE_ENABLE_D3D9) + rendererCreationFunctions.push_back(rx::CreateRenderer); +# endif +# else +# if defined(ANGLE_ENABLE_D3D9) + rendererCreationFunctions.push_back(rx::CreateRenderer); +# endif +# if defined(ANGLE_ENABLE_D3D11) + rendererCreationFunctions.push_back(rx::CreateRenderer); +# endif +# endif } - if (status == EGL_SUCCESS) + for (size_t i = 0; i < rendererCreationFunctions.size(); i++) { - return renderer; + rx::Renderer *renderer = rendererCreationFunctions[i](display, nativeDisplay, requestedDisplayType); + if (renderer->initialize() == EGL_SUCCESS) + { + return renderer; + } + else + { + // Failed to create the renderer, try the next + SafeDelete(renderer); + } } -#endif // ANGLE_ENABLE_D3D9 return NULL; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h index 79578b2458..f1e0fd2d99 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h @@ -1,6 +1,5 @@ -#include "../precompiled.h" // -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // @@ -13,24 +12,15 @@ #include "libGLESv2/Uniform.h" #include "libGLESv2/angletypes.h" +#include "libGLESv2/Caps.h" #if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) -#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 +#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 #endif -const int versionWindowsVista = MAKEWORD(0x00, 0x06); -const int versionWindows7 = MAKEWORD(0x01, 0x06); - -// Return the version of the operating system in a format suitable for ordering -// comparison. -inline int getComparableOSVersion() -{ - DWORD version = GetVersion(); - int majorVersion = LOBYTE(LOWORD(version)); - int minorVersion = HIBYTE(LOWORD(version)); - return MAKEWORD(minorVersion, majorVersion); -} - namespace egl { class Display; @@ -40,31 +30,38 @@ namespace gl { class InfoLog; class ProgramBinary; -class VertexAttribute; +struct LinkedVarying; +struct VertexAttribute; class Buffer; class Texture; class Framebuffer; +struct VertexAttribCurrentValueData; } namespace rx { class TextureStorageInterface2D; class TextureStorageInterfaceCube; +class TextureStorageInterface3D; +class TextureStorageInterface2DArray; class VertexBuffer; class IndexBuffer; class QueryImpl; class FenceImpl; +class BufferImpl; +class VertexArrayImpl; class BufferStorage; -class Blit; struct TranslatedIndexData; class ShaderExecutable; class SwapChain; class RenderTarget; class Image; class TextureStorage; - -typedef void * ShaderBlob; -typedef void (*pCompileFunc)(); +class UniformStorage; +class Texture2DImpl; +class TextureCubeImpl; +class Texture3DImpl; +class Texture2DArrayImpl; struct ConfigDesc { @@ -72,6 +69,7 @@ struct ConfigDesc GLenum depthStencilFormat; GLint multiSample; bool fastConfig; + bool es3Capable; }; struct dx_VertexConstants @@ -94,12 +92,6 @@ enum ShaderType SHADER_GEOMETRY }; -enum D3DWorkaroundType -{ - ANGLE_D3D_WORKAROUND_NONE, - ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER -}; - class Renderer { public: @@ -116,11 +108,14 @@ 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 bool 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::Color &blendColor, + 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; @@ -130,14 +125,18 @@ class Renderer bool ignoreViewport) = 0; virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer) = 0; - virtual void applyShaders(gl::ProgramBinary *programBinary) = 0; - virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) = 0; + virtual 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 bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0; - virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) = 0; + virtual GLenum 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 void applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) = 0; - virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances) = 0; - virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0; + virtual void 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 void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) = 0; @@ -149,20 +148,15 @@ class Renderer virtual bool testDeviceLost(bool notify) = 0; virtual bool testDeviceResettable() = 0; - // Renderer capabilities + // Renderer capabilities (virtual because it is used by egl::Display, do not override) + virtual const gl::Caps &getRendererCaps() const; + virtual const gl::TextureCapsMap &getRendererTextureCaps() const; + virtual const gl::Extensions &getRendererExtensions() const; + virtual DWORD getAdapterVendor() const = 0; virtual std::string getRendererDescription() const = 0; virtual GUID getAdapterIdentifier() const = 0; - virtual bool getBGRATextureSupport() const = 0; - virtual bool getDXT1TextureSupport() = 0; - virtual bool getDXT3TextureSupport() = 0; - virtual bool getDXT5TextureSupport() = 0; - virtual bool getEventQuerySupport() = 0; - virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable) = 0; - virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable) = 0; - virtual bool getLuminanceTextureSupport() = 0; - virtual bool getLuminanceAlphaTextureSupport() = 0; bool getVertexTextureSupport() const { return getMaxVertexTextureImageUnits() > 0; } virtual unsigned int getMaxVertexTextureImageUnits() const = 0; virtual unsigned int getMaxCombinedTextureImageUnits() const = 0; @@ -171,80 +165,117 @@ class Renderer virtual unsigned int getMaxVertexUniformVectors() const = 0; virtual unsigned int getMaxFragmentUniformVectors() const = 0; virtual unsigned int getMaxVaryingVectors() const = 0; - virtual bool getNonPower2TextureSupport() const = 0; - virtual bool getDepthTextureSupport() const = 0; - virtual bool getOcclusionQuerySupport() const = 0; - virtual bool getInstancingSupport() const = 0; - virtual bool getTextureFilterAnisotropySupport() const = 0; - virtual float getTextureMaxAnisotropy() const = 0; + virtual 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 getDerivativeInstructionSupport() 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 float getMaxPointSize() const = 0; - virtual int getMaxViewportDimension() const = 0; - virtual int getMaxTextureWidth() const = 0; - virtual int getMaxTextureHeight() const = 0; - virtual bool get32BitIndexSupport() const = 0; virtual int getMinSwapInterval() const = 0; virtual int getMaxSwapInterval() const = 0; virtual GLsizei getMaxSupportedSamples() const = 0; - - virtual unsigned int getMaxRenderTargets() const = 0; + 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 blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - bool blitRenderTarget, bool blitDepthStencil) = 0; - virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) = 0; + 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; // RenderTarget creation virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth) = 0; - virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) = 0; + virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples) = 0; // Shader operations - virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type) = 0; - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) = 0; + virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers) = 0; + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, D3DWorkaroundType workaround) = 0; + virtual UniformStorage *createUniformStorage(size_t storageSize) = 0; // Image operations virtual Image *createImage() = 0; virtual void generateMipmap(Image *dest, Image *source) = 0; virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain) = 0; - virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) = 0; - virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) = 0; + virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) = 0; + virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) = 0; + virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; + virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0; + + // Texture creation + virtual Texture2DImpl *createTexture2D() = 0; + virtual TextureCubeImpl *createTextureCube() = 0; + virtual Texture3DImpl *createTexture3D() = 0; + virtual Texture2DArrayImpl *createTexture2DArray() = 0; // Buffer creation + virtual BufferImpl *createBuffer() = 0; virtual VertexBuffer *createVertexBuffer() = 0; virtual IndexBuffer *createIndexBuffer() = 0; - virtual BufferStorage *createBufferStorage() = 0; + + // Vertex Array creation + virtual VertexArrayImpl *createVertexArray() = 0; // Query and Fence creation virtual QueryImpl *createQuery(GLenum type) = 0; virtual FenceImpl *createFence() = 0; + // Current GLES client version + void setCurrentClientVersion(int clientVersion) { mCurrentClientVersion = clientVersion; } + int getCurrentClientVersion() const { return mCurrentClientVersion; } + + // Buffer-to-texture and Texture-to-buffer copies + virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0; + virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + 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; protected: - bool initializeCompiler(); - ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, UINT optimizationFlags, bool alternateFlags); - egl::Display *mDisplay; private: DISALLOW_COPY_AND_ASSIGN(Renderer); - HMODULE mD3dCompilerModule; - pCompileFunc mD3DCompileFunc; + virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, gl::Extensions *outExtensions) const = 0; + + mutable bool mCapsInitialized; + mutable gl::Caps mCaps; + mutable gl::TextureCapsMap mTextureCaps; + mutable gl::Extensions mExtensions; + + int mCurrentClientVersion; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderCache.h deleted file mode 100644 index 4391ac271a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderCache.h +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ShaderCache: Defines rx::ShaderCache, a cache of Direct3D shader objects -// keyed by their byte code. - -#ifndef LIBGLESV2_RENDERER_SHADER_CACHE_H_ -#define LIBGLESV2_RENDERER_SHADER_CACHE_H_ - -#include "common/debug.h" - -namespace rx -{ -template -class ShaderCache -{ - public: - ShaderCache() : mDevice(NULL) - { - } - - ~ShaderCache() - { - // Call clear while the device is still valid. - ASSERT(mMap.empty()); - } - - void initialize(IDirect3DDevice9* device) - { - mDevice = device; - } - - ShaderObject *create(const DWORD *function, size_t length) - { - std::string key(reinterpret_cast(function), length); - typename Map::iterator it = mMap.find(key); - if (it != mMap.end()) - { - it->second->AddRef(); - return it->second; - } - - ShaderObject *shader; - HRESULT result = createShader(function, &shader); - if (FAILED(result)) - { - return NULL; - } - - // Random eviction policy. - if (mMap.size() >= kMaxMapSize) - { - mMap.begin()->second->Release(); - mMap.erase(mMap.begin()); - } - - shader->AddRef(); - mMap[key] = shader; - - return shader; - } - - void clear() - { - for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it) - { - it->second->Release(); - } - - mMap.clear(); - } - - private: - DISALLOW_COPY_AND_ASSIGN(ShaderCache); - - const static size_t kMaxMapSize = 100; - - HRESULT createShader(const DWORD *function, IDirect3DVertexShader9 **shader) - { - return mDevice->CreateVertexShader(function, shader); - } - - HRESULT createShader(const DWORD *function, IDirect3DPixelShader9 **shader) - { - return mDevice->CreatePixelShader(function, shader); - } - -#ifndef HASH_MAP -# ifdef _MSC_VER -# define HASH_MAP stdext::hash_map -# else -# define HASH_MAP std::unordered_map -# endif -#endif - - typedef HASH_MAP Map; - Map mMap; - - IDirect3DDevice9 *mDevice; -}; - -typedef ShaderCache VertexShaderCache; -typedef ShaderCache PixelShaderCache; - -} - -#endif // LIBGLESV2_RENDERER_SHADER_CACHE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h index 293e340845..054d00a712 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h @@ -11,6 +11,7 @@ #define LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_ #include "common/angleutils.h" +#include "common/debug.h" namespace rx { @@ -18,32 +19,44 @@ namespace rx class ShaderExecutable { public: - ShaderExecutable(const void *function, size_t length) : mLength(length) + ShaderExecutable(const void *function, size_t length) + : mFunctionBuffer(length) { - mFunction = new char[length]; - memcpy(mFunction, function, length); - } - - virtual ~ShaderExecutable() - { - delete[] mFunction; + memcpy(mFunctionBuffer.data(), function, length); } - void *getFunction() const + virtual ~ShaderExecutable() {} + + const uint8_t *getFunction() const { - return mFunction; + return mFunctionBuffer.data(); } size_t getLength() const { - return mLength; + return mFunctionBuffer.size(); } private: DISALLOW_COPY_AND_ASSIGN(ShaderExecutable); - void *mFunction; - const size_t mLength; + std::vector mFunctionBuffer; +}; + +class UniformStorage +{ + public: + UniformStorage(size_t initialSize) + : mSize(initialSize) + { + } + + virtual ~UniformStorage() {} + + size_t size() const { return mSize; } + + private: + size_t mSize; }; } diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h index 8231fbcb25..77546f81e7 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h @@ -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,6 +10,7 @@ #ifndef LIBGLESV2_RENDERER_SWAPCHAIN_H_ #define LIBGLESV2_RENDERER_SWAPCHAIN_H_ +#include #include "common/angleutils.h" #if !defined(ANGLE_FORCE_VSYNC_OFF) @@ -20,6 +20,14 @@ namespace rx { +enum SwapFlags +{ + SWAP_NORMAL = 0, + SWAP_ROTATE_90 = 1, + SWAP_ROTATE_270 = 2, + SWAP_ROTATE_180 = SWAP_ROTATE_90|SWAP_ROTATE_270, +}; + class SwapChain { public: @@ -32,13 +40,13 @@ class SwapChain virtual EGLint resize(EGLint backbufferWidth, EGLint backbufferSize) = 0; virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0; - virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0; + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags) = 0; virtual void recreate() = 0; virtual HANDLE getShareHandle() {return mShareHandle;}; protected: - const EGLNativeWindowType mWindow; // Window that the surface is created for. + const EGLNativeWindowType mWindow; // Window that the surface is created for. const GLenum mBackBufferFormat; const GLenum mDepthBufferFormat; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h new file mode 100644 index 0000000000..35c9166023 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h @@ -0,0 +1,166 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureImpl.h: Defines the abstract rx::TextureImpl classes. + +#ifndef LIBGLESV2_RENDERER_TEXTUREIMPL_H_ +#define LIBGLESV2_RENDERER_TEXTUREIMPL_H_ + +#include "common/angleutils.h" + +namespace egl +{ +class Surface; +} + +namespace gl +{ +class Framebuffer; +struct PixelUnpackState; +struct SamplerState; +} + +namespace rx +{ + +class Image; +class RenderTarget; +class Renderer; +class TextureStorageInterface; + +class Texture2DImpl +{ + public: + virtual ~Texture2DImpl() {} + + // 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 Image *getImage(int level, int layer) 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 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, GLint layer) = 0; + virtual RenderTarget *getDepthStencil(GLint level, GLint layer) = 0; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTUREIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.cpp deleted file mode 100644 index 00b316f1cc..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TextureStorage.cpp: Implements the abstract rx::TextureStorageInterface class and its concrete derived -// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the -// GPU-side texture. - -#include "libGLESv2/renderer/TextureStorage.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/Texture.h" - -#include "common/debug.h" - -namespace rx -{ -unsigned int TextureStorageInterface::mCurrentTextureSerial = 1; - -TextureStorageInterface::TextureStorageInterface() - : mTextureSerial(issueTextureSerial()), - mInstance(NULL) -{ -} - -TextureStorageInterface::~TextureStorageInterface() -{ - delete mInstance; -} - -bool TextureStorageInterface::isRenderTarget() const -{ - return mInstance->isRenderTarget(); -} - - -bool TextureStorageInterface::isManaged() const -{ - return mInstance->isManaged(); -} - -unsigned int TextureStorageInterface::getTextureSerial() const -{ - return mTextureSerial; -} - -unsigned int TextureStorageInterface::issueTextureSerial() -{ - return mCurrentTextureSerial++; -} - -int TextureStorageInterface::getLodOffset() const -{ - return mInstance->getLodOffset(); -} - - -int TextureStorageInterface::levelCount() -{ - return mInstance->levelCount(); -} - -TextureStorageInterface2D::TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain) - : mRenderTargetSerial(gl::RenderbufferStorage::issueSerial()) -{ - mInstance = renderer->createTextureStorage2D(swapchain); -} - -TextureStorageInterface2D::TextureStorageInterface2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) - : mRenderTargetSerial(gl::RenderbufferStorage::issueSerial()) -{ - mInstance = renderer->createTextureStorage2D(levels, internalformat, usage, forceRenderable, width, height); -} - -TextureStorageInterface2D::~TextureStorageInterface2D() -{ -} - -RenderTarget *TextureStorageInterface2D::getRenderTarget() const -{ - return mInstance->getRenderTarget(); -} - -void TextureStorageInterface2D::generateMipmap(int level) -{ - mInstance->generateMipmap(level); -} - -unsigned int TextureStorageInterface2D::getRenderTargetSerial(GLenum target) const -{ - return mRenderTargetSerial; -} - -TextureStorageInterfaceCube::TextureStorageInterfaceCube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) - : mFirstRenderTargetSerial(gl::RenderbufferStorage::issueCubeSerials()) -{ - mInstance = renderer->createTextureStorageCube(levels, internalformat, usage, forceRenderable, size); -} - -TextureStorageInterfaceCube::~TextureStorageInterfaceCube() -{ -} - -RenderTarget *TextureStorageInterfaceCube::getRenderTarget(GLenum faceTarget) const -{ - return mInstance->getRenderTarget(faceTarget); -} - -void TextureStorageInterfaceCube::generateMipmap(int face, int level) -{ - mInstance->generateMipmap(face, level); -} - -unsigned int TextureStorageInterfaceCube::getRenderTargetSerial(GLenum target) const -{ - return mFirstRenderTargetSerial + gl::TextureCubeMap::faceIndex(target); -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.h b/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.h deleted file mode 100644 index edddb75f3f..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureStorage.h +++ /dev/null @@ -1,110 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TextureStorage.h: Defines the abstract rx::TextureStorageInterface class and its concrete derived -// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the -// GPU-side texture. - -#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ -#define LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ - -#include "common/debug.h" - -namespace rx -{ -class Renderer; -class SwapChain; -class RenderTarget; -class Blit; - -class TextureStorage -{ - public: - TextureStorage() {}; - virtual ~TextureStorage() {}; - - virtual int getLodOffset() const = 0; - virtual bool isRenderTarget() const = 0; - virtual bool isManaged() const = 0; - virtual int levelCount() = 0; - - virtual RenderTarget *getRenderTarget() = 0; - virtual RenderTarget *getRenderTarget(GLenum faceTarget) = 0; - virtual void generateMipmap(int level) = 0; - virtual void generateMipmap(int face, int level) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage); - -}; - -class TextureStorageInterface -{ - public: - TextureStorageInterface(); - virtual ~TextureStorageInterface(); - - TextureStorage *getStorageInstance() { return mInstance; } - - unsigned int getTextureSerial() const; - virtual unsigned int getRenderTargetSerial(GLenum target) const = 0; - - virtual int getLodOffset() const; - virtual bool isRenderTarget() const; - virtual bool isManaged() const; - virtual int levelCount(); - - protected: - TextureStorage *mInstance; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface); - - const unsigned int mTextureSerial; - static unsigned int issueTextureSerial(); - - static unsigned int mCurrentTextureSerial; -}; - -class TextureStorageInterface2D : public TextureStorageInterface -{ - public: - TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain); - TextureStorageInterface2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); - virtual ~TextureStorageInterface2D(); - - void generateMipmap(int level); - RenderTarget *getRenderTarget() const; - - virtual unsigned int getRenderTargetSerial(GLenum target) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface2D); - - const unsigned int mRenderTargetSerial; -}; - -class TextureStorageInterfaceCube : public TextureStorageInterface -{ - public: - TextureStorageInterfaceCube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); - virtual ~TextureStorageInterfaceCube(); - - void generateMipmap(int face, int level); - RenderTarget *getRenderTarget(GLenum faceTarget) const; - - virtual unsigned int getRenderTargetSerial(GLenum target) const; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorageInterfaceCube); - - const unsigned int mFirstRenderTargetSerial; -}; - -} - -#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ - diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h new file mode 100644 index 0000000000..b013f9cdf4 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h @@ -0,0 +1,32 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexAttribImpl.h: Defines the abstract rx::VertexAttribImpl class. + +#ifndef LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_ +#define LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_ + +#include "common/angleutils.h" +#include "libGLESv2/Buffer.h" +#include "libGLESv2/VertexAttribute.h" + +namespace rx +{ + +class VertexArrayImpl +{ + public: + virtual ~VertexArrayImpl() { } + + virtual void setElementArrayBuffer(const gl::Buffer *buffer) = 0; + virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) = 0; + virtual void setAttributeDivisor(size_t idx, GLuint divisor) = 0; + virtual void enableAttribute(size_t idx, bool enabledState) = 0; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp deleted file mode 100644 index a073d95033..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.cpp +++ /dev/null @@ -1,292 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface -// class with derivations, classes that perform graphics API agnostic vertex buffer operations. - -#include "libGLESv2/renderer/VertexBuffer.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/Context.h" - -namespace rx -{ - -unsigned int VertexBuffer::mNextSerial = 1; - -VertexBuffer::VertexBuffer() -{ - updateSerial(); -} - -VertexBuffer::~VertexBuffer() -{ -} - -void VertexBuffer::updateSerial() -{ - mSerial = mNextSerial++; -} - -unsigned int VertexBuffer::getSerial() const -{ - return mSerial; -} - -VertexBufferInterface::VertexBufferInterface(rx::Renderer *renderer, bool dynamic) : mRenderer(renderer) -{ - mDynamic = dynamic; - mWritePosition = 0; - mReservedSpace = 0; - - mVertexBuffer = renderer->createVertexBuffer(); -} - -VertexBufferInterface::~VertexBufferInterface() -{ - delete mVertexBuffer; -} - -unsigned int VertexBufferInterface::getSerial() const -{ - return mVertexBuffer->getSerial(); -} - -unsigned int VertexBufferInterface::getBufferSize() const -{ - return mVertexBuffer->getBufferSize(); -} - -bool VertexBufferInterface::setBufferSize(unsigned int size) -{ - if (mVertexBuffer->getBufferSize() == 0) - { - return mVertexBuffer->initialize(size, mDynamic); - } - else - { - return mVertexBuffer->setBufferSize(size); - } -} - -unsigned int VertexBufferInterface::getWritePosition() const -{ - return mWritePosition; -} - -void VertexBufferInterface::setWritePosition(unsigned int writePosition) -{ - mWritePosition = writePosition; -} - -bool VertexBufferInterface::discard() -{ - return mVertexBuffer->discard(); -} - -bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, - unsigned int *outStreamOffset) -{ - unsigned int spaceRequired; - if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired)) - { - return false; - } - - if (mWritePosition + spaceRequired < mWritePosition) - { - return false; - } - - if (!reserveSpace(mReservedSpace)) - { - return false; - } - mReservedSpace = 0; - - if (!mVertexBuffer->storeVertexAttributes(attrib, start, count, instances, mWritePosition)) - { - return false; - } - - if (outStreamOffset) - { - *outStreamOffset = mWritePosition; - } - - mWritePosition += spaceRequired; - - return true; -} - -bool VertexBufferInterface::storeRawData(const void* data, unsigned int size, unsigned int *outStreamOffset) -{ - if (mWritePosition + size < mWritePosition) - { - return false; - } - - if (!reserveSpace(mReservedSpace)) - { - return false; - } - mReservedSpace = 0; - - if (!mVertexBuffer->storeRawData(data, size, mWritePosition)) - { - return false; - } - - if (outStreamOffset) - { - *outStreamOffset = mWritePosition; - } - - mWritePosition += size; - - return true; -} - -bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances) -{ - unsigned int requiredSpace; - if (!mVertexBuffer->getSpaceRequired(attribute, count, instances, &requiredSpace)) - { - return false; - } - - // Protect against integer overflow - if (mReservedSpace + requiredSpace < mReservedSpace) - { - return false; - } - - mReservedSpace += requiredSpace; - return true; -} - -bool VertexBufferInterface::reserveRawDataSpace(unsigned int size) -{ - // Protect against integer overflow - if (mReservedSpace + size < mReservedSpace) - { - return false; - } - - mReservedSpace += size; - return true; -} - -VertexBuffer* VertexBufferInterface::getVertexBuffer() const -{ - return mVertexBuffer; -} - - -StreamingVertexBufferInterface::StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true) -{ - setBufferSize(initialSize); -} - -StreamingVertexBufferInterface::~StreamingVertexBufferInterface() -{ -} - -bool StreamingVertexBufferInterface::reserveSpace(unsigned int size) -{ - bool result = true; - unsigned int curBufferSize = getBufferSize(); - if (size > curBufferSize) - { - result = setBufferSize(std::max(size, 3 * curBufferSize / 2)); - setWritePosition(0); - } - else if (getWritePosition() + size > curBufferSize) - { - if (!discard()) - { - return false; - } - setWritePosition(0); - } - - return result; -} - -StaticVertexBufferInterface::StaticVertexBufferInterface(rx::Renderer *renderer) : VertexBufferInterface(renderer, false) -{ -} - -StaticVertexBufferInterface::~StaticVertexBufferInterface() -{ -} - -bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attribute, unsigned int *outStreamOffset) -{ - for (unsigned int element = 0; element < mCache.size(); element++) - { - if (mCache[element].type == attribute.mType && - mCache[element].size == attribute.mSize && - mCache[element].stride == attribute.stride() && - mCache[element].normalized == attribute.mNormalized) - { - if (mCache[element].attributeOffset == attribute.mOffset % attribute.stride()) - { - if (outStreamOffset) - { - *outStreamOffset = mCache[element].streamOffset; - } - return true; - } - } - } - - return false; -} - -bool StaticVertexBufferInterface::reserveSpace(unsigned int size) -{ - unsigned int curSize = getBufferSize(); - if (curSize == 0) - { - setBufferSize(size); - return true; - } - else if (curSize >= size) - { - return true; - } - else - { - UNREACHABLE(); // Static vertex buffers can't be resized - return false; - } -} - -bool StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, - unsigned int *outStreamOffset) -{ - unsigned int streamOffset; - if (VertexBufferInterface::storeVertexAttributes(attrib, start, count, instances, &streamOffset)) - { - int attributeOffset = attrib.mOffset % attrib.stride(); - VertexElement element = { attrib.mType, attrib.mSize, attrib.stride(), attrib.mNormalized, attributeOffset, streamOffset }; - mCache.push_back(element); - - if (outStreamOffset) - { - *outStreamOffset = streamOffset; - } - - return true; - } - else - { - return false; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h deleted file mode 100644 index cbafdd20f6..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexBuffer.h +++ /dev/null @@ -1,139 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexBuffer.h: Defines the abstract VertexBuffer class and VertexBufferInterface -// class with derivations, classes that perform graphics API agnostic vertex buffer operations. - -#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER_H_ -#define LIBGLESV2_RENDERER_VERTEXBUFFER_H_ - -#include "common/angleutils.h" - -namespace gl -{ -class VertexAttribute; -} - -namespace rx -{ -class Renderer; - -class VertexBuffer -{ - public: - VertexBuffer(); - virtual ~VertexBuffer(); - - virtual bool initialize(unsigned int size, bool dynamicUsage) = 0; - - virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, - GLsizei instances, unsigned int offset) = 0; - virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset) = 0; - - virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, - unsigned int *outSpaceRequired) const = 0; - - virtual bool requiresConversion(const gl::VertexAttribute &attrib) const = 0; - - virtual unsigned int getBufferSize() const = 0; - virtual bool setBufferSize(unsigned int size) = 0; - virtual bool discard() = 0; - - unsigned int getSerial() const; - - protected: - void updateSerial(); - - private: - DISALLOW_COPY_AND_ASSIGN(VertexBuffer); - - unsigned int mSerial; - static unsigned int mNextSerial; -}; - -class VertexBufferInterface -{ - public: - VertexBufferInterface(rx::Renderer *renderer, bool dynamic); - virtual ~VertexBufferInterface(); - - bool reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances); - bool reserveRawDataSpace(unsigned int size); - - unsigned int getBufferSize() const; - - unsigned int getSerial() const; - - virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, - unsigned int *outStreamOffset); - virtual bool storeRawData(const void* data, unsigned int size, unsigned int *outStreamOffset); - - VertexBuffer* getVertexBuffer() const; - - protected: - virtual bool reserveSpace(unsigned int size) = 0; - - unsigned int getWritePosition() const; - void setWritePosition(unsigned int writePosition); - - bool discard(); - - bool setBufferSize(unsigned int size); - - private: - DISALLOW_COPY_AND_ASSIGN(VertexBufferInterface); - - rx::Renderer *const mRenderer; - - VertexBuffer* mVertexBuffer; - - unsigned int mWritePosition; - unsigned int mReservedSpace; - bool mDynamic; -}; - -class StreamingVertexBufferInterface : public VertexBufferInterface -{ - public: - StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize); - ~StreamingVertexBufferInterface(); - - protected: - bool reserveSpace(unsigned int size); -}; - -class StaticVertexBufferInterface : public VertexBufferInterface -{ - public: - explicit StaticVertexBufferInterface(rx::Renderer *renderer); - ~StaticVertexBufferInterface(); - - bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, - unsigned int *outStreamOffset); - - bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamOffset); - - protected: - bool reserveSpace(unsigned int size); - - private: - struct VertexElement - { - GLenum type; - GLint size; - GLsizei stride; - bool normalized; - int attributeOffset; - - unsigned int streamOffset; - }; - - std::vector mCache; -}; - -} - -#endif // LIBGLESV2_RENDERER_VERTEXBUFFER_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp deleted file mode 100644 index 8034aed8c9..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.cpp +++ /dev/null @@ -1,304 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexDataManager.h: Defines the VertexDataManager, a class that -// runs the Buffer translation process. - -#include "libGLESv2/renderer/VertexDataManager.h" -#include "libGLESv2/renderer/BufferStorage.h" - -#include "libGLESv2/Buffer.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/renderer/VertexBuffer.h" - -namespace -{ - enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 }; - // This has to be at least 4k or else it fails on ATI cards. - enum { CONSTANT_VERTEX_BUFFER_SIZE = 4096 }; -} - -namespace rx -{ - -static int elementsInBuffer(const gl::VertexAttribute &attribute, unsigned int size) -{ - // Size cannot be larger than a GLsizei - if (size > static_cast(std::numeric_limits::max())) - { - size = static_cast(std::numeric_limits::max()); - } - - GLsizei stride = attribute.stride(); - return (size - attribute.mOffset % stride + (stride - attribute.typeSize())) / stride; -} - -static int StreamingBufferElementCount(const gl::VertexAttribute &attribute, int vertexDrawCount, int instanceDrawCount) -{ - // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices. - // - // A vertex attribute with a positive divisor loads one instanced vertex for every set of - // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances. - if (instanceDrawCount > 0 && attribute.mDivisor > 0) - { - return instanceDrawCount / attribute.mDivisor; - } - - return vertexDrawCount; -} - -VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer) -{ - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentValue[i][0] = std::numeric_limits::quiet_NaN(); - mCurrentValue[i][1] = std::numeric_limits::quiet_NaN(); - mCurrentValue[i][2] = std::numeric_limits::quiet_NaN(); - mCurrentValue[i][3] = std::numeric_limits::quiet_NaN(); - mCurrentValueBuffer[i] = NULL; - mCurrentValueOffsets[i] = 0; - } - - mStreamingBuffer = new StreamingVertexBufferInterface(renderer, INITIAL_STREAM_BUFFER_SIZE); - - if (!mStreamingBuffer) - { - ERR("Failed to allocate the streaming vertex buffer."); - } -} - -VertexDataManager::~VertexDataManager() -{ - delete mStreamingBuffer; - - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - delete mCurrentValueBuffer[i]; - } -} - -static bool directStoragePossible(VertexBufferInterface* vb, const gl::VertexAttribute& attrib) -{ - gl::Buffer *buffer = attrib.mBoundBuffer.get(); - BufferStorage *storage = buffer ? buffer->getStorage() : NULL; - - const bool isAligned = (attrib.stride() % 4 == 0) && (attrib.mOffset % 4 == 0); - - return storage && storage->supportsDirectBinding() && !vb->getVertexBuffer()->requiresConversion(attrib) && isAligned; -} - -GLenum VertexDataManager::prepareVertexData(const gl::VertexAttribute attribs[], gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *translated, GLsizei instances) -{ - if (!mStreamingBuffer) - { - return GL_OUT_OF_MEMORY; - } - - for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) - { - translated[attributeIndex].active = (programBinary->getSemanticIndex(attributeIndex) != -1); - } - - // Invalidate static buffers that don't contain matching attributes - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - if (translated[i].active && attribs[i].mArrayEnabled) - { - gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); - StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; - - if (staticBuffer && staticBuffer->getBufferSize() > 0 && !staticBuffer->lookupAttribute(attribs[i], NULL) && - !directStoragePossible(staticBuffer, attribs[i])) - { - buffer->invalidateStaticData(); - } - } - } - - // Reserve the required space in the buffers - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - if (translated[i].active && attribs[i].mArrayEnabled) - { - gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); - StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; - VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); - - if (!directStoragePossible(vertexBuffer, attribs[i])) - { - if (staticBuffer) - { - if (staticBuffer->getBufferSize() == 0) - { - int totalCount = elementsInBuffer(attribs[i], buffer->size()); - if (!staticBuffer->reserveVertexSpace(attribs[i], totalCount, 0)) - { - return GL_OUT_OF_MEMORY; - } - } - } - else - { - int totalCount = StreamingBufferElementCount(attribs[i], count, instances); - - // Undefined behaviour: - // We can return INVALID_OPERATION if our vertex attribute does not have enough backing data. - if (buffer && elementsInBuffer(attribs[i], buffer->size()) < totalCount) - { - return GL_INVALID_OPERATION; - } - - if (!mStreamingBuffer->reserveVertexSpace(attribs[i], totalCount, instances)) - { - return GL_OUT_OF_MEMORY; - } - } - } - } - } - - // Perform the vertex data translations - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - if (translated[i].active) - { - if (attribs[i].mArrayEnabled) - { - gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); - - if (!buffer && attribs[i].mPointer == NULL) - { - // This is an application error that would normally result in a crash, but we catch it and return an error - ERR("An enabled vertex array has no buffer and no pointer."); - return GL_INVALID_OPERATION; - } - - StaticVertexBufferInterface *staticBuffer = buffer ? buffer->getStaticVertexBuffer() : NULL; - VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast(mStreamingBuffer); - - BufferStorage *storage = buffer ? buffer->getStorage() : NULL; - bool directStorage = directStoragePossible(vertexBuffer, attribs[i]); - - unsigned int streamOffset = 0; - unsigned int outputElementSize = 0; - - if (directStorage) - { - outputElementSize = attribs[i].stride(); - streamOffset = attribs[i].mOffset + outputElementSize * start; - storage->markBufferUsage(); - } - 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].mOffset / attribs[i].stride(); - - if (!staticBuffer->storeVertexAttributes(attribs[i], -startIndex, totalCount, 0, &streamOffset)) - { - return GL_OUT_OF_MEMORY; - } - } - - unsigned int firstElementOffset = (attribs[i].mOffset / attribs[i].stride()) * outputElementSize; - unsigned int startOffset = (instances == 0 || attribs[i].mDivisor == 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], 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].mDivisor; - - translated[i].attribute = &attribs[i]; - translated[i].stride = outputElementSize; - translated[i].offset = streamOffset; - } - else - { - if (!mCurrentValueBuffer[i]) - { - mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE); - } - - StreamingVertexBufferInterface *buffer = mCurrentValueBuffer[i]; - - if (mCurrentValue[i][0] != attribs[i].mCurrentValue[0] || - mCurrentValue[i][1] != attribs[i].mCurrentValue[1] || - mCurrentValue[i][2] != attribs[i].mCurrentValue[2] || - mCurrentValue[i][3] != attribs[i].mCurrentValue[3]) - { - unsigned int requiredSpace = sizeof(float) * 4; - if (!buffer->reserveRawDataSpace(requiredSpace)) - { - return GL_OUT_OF_MEMORY; - } - - unsigned int streamOffset; - if (!buffer->storeRawData(attribs[i].mCurrentValue, requiredSpace, &streamOffset)) - { - return GL_OUT_OF_MEMORY; - } - - mCurrentValue[i][0] = attribs[i].mCurrentValue[0]; - mCurrentValue[i][1] = attribs[i].mCurrentValue[1]; - mCurrentValue[i][2] = attribs[i].mCurrentValue[2]; - mCurrentValue[i][3] = attribs[i].mCurrentValue[3]; - mCurrentValueOffsets[i] = streamOffset; - } - - translated[i].storage = NULL; - translated[i].vertexBuffer = mCurrentValueBuffer[i]->getVertexBuffer(); - translated[i].serial = mCurrentValueBuffer[i]->getSerial(); - translated[i].divisor = 0; - - translated[i].attribute = &attribs[i]; - translated[i].stride = 0; - translated[i].offset = mCurrentValueOffsets[i]; - } - } - } - - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - if (translated[i].active && attribs[i].mArrayEnabled) - { - gl::Buffer *buffer = attribs[i].mBoundBuffer.get(); - - if (buffer) - { - buffer->promoteStaticUsage(count * attribs[i].typeSize()); - } - } - } - - return GL_NO_ERROR; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h deleted file mode 100644 index 1a8786552a..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexDataManager.h +++ /dev/null @@ -1,65 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexDataManager.h: Defines the VertexDataManager, a class that -// runs the Buffer translation process. - -#ifndef LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ -#define LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ - -#include "libGLESv2/Constants.h" -#include "common/angleutils.h" - -namespace gl -{ -class VertexAttribute; -class ProgramBinary; -} - -namespace rx -{ -class BufferStorage; -class StreamingVertexBufferInterface; -class VertexBuffer; -class Renderer; - -struct TranslatedAttribute -{ - bool active; - - const gl::VertexAttribute *attribute; - unsigned int offset; - unsigned int stride; // 0 means not to advance the read pointer at all - - VertexBuffer *vertexBuffer; - BufferStorage *storage; - unsigned int serial; - unsigned int divisor; -}; - -class VertexDataManager -{ - public: - VertexDataManager(rx::Renderer *renderer); - virtual ~VertexDataManager(); - - GLenum prepareVertexData(const gl::VertexAttribute attribs[], gl::ProgramBinary *programBinary, GLint start, GLsizei count, TranslatedAttribute *outAttribs, GLsizei instances); - - private: - DISALLOW_COPY_AND_ASSIGN(VertexDataManager); - - rx::Renderer *const mRenderer; - - StreamingVertexBufferInterface *mStreamingBuffer; - - float mCurrentValue[gl::MAX_VERTEX_ATTRIBS][4]; - StreamingVertexBufferInterface *mCurrentValueBuffer[gl::MAX_VERTEX_ATTRIBS]; - std::size_t mCurrentValueOffsets[gl::MAX_VERTEX_ATTRIBS]; -}; - -} - -#endif // LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp new file mode 100644 index 0000000000..765089cc96 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp @@ -0,0 +1,23 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// copyimage.cpp: Defines image copying functions + +#include "libGLESv2/renderer/copyImage.h" + +namespace rx +{ + +void CopyBGRAUByteToRGBAUByte(const void *source, void *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 +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h new file mode 100644 index 0000000000..9b94404ee3 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h @@ -0,0 +1,42 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// copyimage.h: Defines image copying functions + +#ifndef LIBGLESV2_RENDERER_COPYIMAGE_H_ +#define LIBGLESV2_RENDERER_COPYIMAGE_H_ + +#include "common/mathutil.h" +#include "libGLESv2/angletypes.h" + +namespace rx +{ + +template +void ReadColor(const void *source, void *dest) +{ + sourceType::readColor(reinterpret_cast*>(dest), reinterpret_cast(source)); +} + +template +void WriteColor(const void *source, void *dest) +{ + destType::writeColor(reinterpret_cast(dest), reinterpret_cast*>(source)); +} + +template +void CopyPixel(const void *source, void *dest) +{ + colorDataType temp; + ReadColor(source, &temp); + WriteColor(&temp, dest); +} + +void CopyBGRAUByteToRGBAUByte(const void *source, void *dest); + +} + +#endif // LIBGLESV2_RENDERER_COPYIMAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h b/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h new file mode 100644 index 0000000000..aca031701e --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h @@ -0,0 +1,309 @@ +// +// 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. +// + +// copyvertex.h: Defines vertex buffer copying and conversion functions + +#ifndef LIBGLESV2_RENDERER_COPYVERTEX_H_ +#define LIBGLESV2_RENDERER_COPYVERTEX_H_ + +#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) +{ + 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; + + 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); + + offsetOutput[i] = offsetInput[i]; + } + } +} + +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; + } + } +} + +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)); + } +} + +#endif // LIBGLESV2_RENDERER_COPYVERTEX_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp new file mode 100644 index 0000000000..08457af76d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp @@ -0,0 +1,83 @@ +#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. +// + +// 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/main.h" + +namespace rx +{ + +unsigned int BufferD3D::mNextSerial = 1; + +BufferD3D::BufferD3D() + : BufferImpl(), + mStaticVertexBuffer(NULL), + mStaticIndexBuffer(NULL) +{ + updateSerial(); +} + +BufferD3D::~BufferD3D() +{ + SafeDelete(mStaticVertexBuffer); + SafeDelete(mStaticIndexBuffer); +} + +BufferD3D *BufferD3D::makeBufferD3D(BufferImpl *buffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(BufferD3D*, buffer)); + return static_cast(buffer); +} + +void BufferD3D::updateSerial() +{ + mSerial = mNextSerial++; +} + +void BufferD3D::initializeStaticData() +{ + if (!mStaticVertexBuffer) + { + mStaticVertexBuffer = new rx::StaticVertexBufferInterface(getRenderer()); + } + if (!mStaticIndexBuffer) + { + mStaticIndexBuffer = new rx::StaticIndexBufferInterface(getRenderer()); + } +} + +void BufferD3D::invalidateStaticData() +{ + if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)) + { + SafeDelete(mStaticVertexBuffer); + SafeDelete(mStaticIndexBuffer); + } + + mUnmodifiedDataUse = 0; +} + +// Creates static buffers if sufficient used data has been left unmodified +void BufferD3D::promoteStaticUsage(int dataSize) +{ + if (!mStaticVertexBuffer && !mStaticIndexBuffer) + { + mUnmodifiedDataUse += dataSize; + + if (mUnmodifiedDataUse > 3 * getSize()) + { + initializeStaticData(); + } + } +} + +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h new file mode 100644 index 0000000000..8e204b9139 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h @@ -0,0 +1,60 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// BufferImpl.h: Defines the abstract rx::BufferImpl class. + +#ifndef LIBGLESV2_RENDERER_BUFFERD3D_H_ +#define LIBGLESV2_RENDERER_BUFFERD3D_H_ + +#include "libGLESv2/renderer/BufferImpl.h" +#include "libGLESv2/angletypes.h" +#include "libGLESv2/renderer/IndexRangeCache.h" + +namespace rx +{ + +class Renderer; +class StaticIndexBufferInterface; +class StaticVertexBufferInterface; + +class BufferD3D : public BufferImpl +{ + public: + BufferD3D(); + virtual ~BufferD3D(); + + static BufferD3D *makeBufferD3D(BufferImpl *buffer); + + 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(); + void promoteStaticUsage(int dataSize); + + protected: + unsigned int mSerial; + static unsigned int mNextSerial; + + void updateSerial(); + + rx::StaticVertexBufferInterface *mStaticVertexBuffer; + rx::StaticIndexBufferInterface *mStaticIndexBuffer; + rx::IndexRangeCache mIndexRangeCache; + unsigned int mUnmodifiedDataUse; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFERIMPLD3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp new file mode 100644 index 0000000000..e3b88d506d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp @@ -0,0 +1,171 @@ +#include "precompiled.h" +#include "libGLESv2/renderer/d3d/HLSLCompiler.h" +#include "libGLESv2/Program.h" +#include "libGLESv2/main.h" + +#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) + +#define D3DCOMPILER_DLL L"d3dcompiler_43.dll" + +HRESULT WINAPI D3DCompile(const void *data, SIZE_T data_size, const char *filename, + const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, + const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); +typedef HRESULT (WINAPI *pD3DCompile)(const void *data, SIZE_T data_size, const char *filename, + const D3D_SHADER_MACRO *defines, ID3DInclude *include, const char *entrypoint, + const char *target, UINT sflags, UINT eflags, ID3DBlob **shader, ID3DBlob **error_messages); + +#endif // __MINGW32__ && !D3DCOMPILER_DLL + +#ifndef QT_D3DCOMPILER_DLL +#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL +#endif + +#ifndef LoadLibrary +#define LoadLibrary(dll) LoadPackagedLibrary(dll, NULL) +#endif + +namespace rx +{ + +HLSLCompiler::HLSLCompiler() + : mD3DCompilerModule(NULL), + mD3DCompileFunc(NULL) +{ +} + +HLSLCompiler::~HLSLCompiler() +{ + release(); +} + +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. + static const char *d3dCompilerNames[] = ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES; + + for (size_t i = 0; i < ArraySize(d3dCompilerNames); ++i) + { + if (GetModuleHandleExA(0, d3dCompilerNames[i], &mD3DCompilerModule)) + { + break; + } + } +#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES + + // Load the compiler DLL specified by the environment, or default to QT_D3DCOMPILER_DLL + const wchar_t *defaultCompiler = _wgetenv(L"QT_D3DCOMPILER_DLL"); + if (!defaultCompiler) + defaultCompiler = QT_D3DCOMPILER_DLL; + + const wchar_t *compilerDlls[] = { + defaultCompiler, + L"d3dcompiler_47.dll", + L"d3dcompiler_46.dll", + L"d3dcompiler_45.dll", + L"d3dcompiler_44.dll", + L"d3dcompiler_43.dll", + 0 + }; + + // Load the first available known compiler DLL + for (int i = 0; compilerDlls[i]; ++i) + { + mD3DCompilerModule = LoadLibrary(compilerDlls[i]); + if (mD3DCompilerModule) + break; + } + + if (!mD3DCompilerModule) + { + ERR("No D3D compiler module found - aborting!\n"); + return false; + } + + mD3DCompileFunc = reinterpret_cast(GetProcAddress(mD3DCompilerModule, "D3DCompile")); + ASSERT(mD3DCompileFunc); +#else + mD3DCompileFunc = reinterpret_cast(&D3DCompile); +#endif + return mD3DCompileFunc != NULL; +} + +void HLSLCompiler::release() +{ + if (mD3DCompilerModule) + { + FreeLibrary(mD3DCompilerModule); + mD3DCompilerModule = NULL; + mD3DCompileFunc = NULL; + } +} + +ShaderBlob *HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, + const UINT optimizationFlags[], const char *flagNames[], int attempts) const +{ +#if !defined(ANGLE_PLATFORM_WINRT) + ASSERT(mD3DCompilerModule && mD3DCompileFunc); +#endif + + if (!hlsl) + { + return NULL; + } + + pD3DCompile compileFunc = reinterpret_cast(mD3DCompileFunc); + for (int i = 0; i < attempts; ++i) + { + ID3DBlob *errorMessage = NULL; + ID3DBlob *binary = NULL; + + HRESULT result = compileFunc(hlsl, strlen(hlsl), gl::g_fakepath, NULL, NULL, "main", profile, optimizationFlags[i], 0, &binary, &errorMessage); + + if (errorMessage) + { + const char *message = (const char*)errorMessage->GetBufferPointer(); + + infoLog.appendSanitized(message); + TRACE("\n%s", hlsl); + TRACE("\n%s", message); + + SafeRelease(errorMessage); + } + + if (SUCCEEDED(result)) + { + return (ShaderBlob*)binary; + } + else + { + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, (ShaderBlob*)NULL); + } + + infoLog.append("Warning: D3D shader compilation failed with "); + infoLog.append(flagNames[i]); + infoLog.append(" flags."); + if (i + 1 < attempts) + { + infoLog.append(" Retrying with "); + infoLog.append(flagNames[i + 1]); + infoLog.append(".\n"); + } + } + } + + return NULL; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h new file mode 100644 index 0000000000..0ce9e44be5 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h @@ -0,0 +1,38 @@ +#ifndef LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ +#define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ + +#include "common/angleutils.h" + +namespace gl +{ +class InfoLog; +} + +namespace rx +{ + +typedef void* ShaderBlob; +typedef void(*CompileFuncPtr)(); + +class HLSLCompiler +{ + public: + HLSLCompiler(); + ~HLSLCompiler(); + + bool initialize(); + void release(); + + ShaderBlob *compileToBinary(gl::InfoLog &infoLog, const char *hlsl, const char *profile, + const UINT optimizationFlags[], const char *flagNames[], int attempts) const; + + private: + DISALLOW_COPY_AND_ASSIGN(HLSLCompiler); + + HMODULE mD3DCompilerModule; + CompileFuncPtr mD3DCompileFunc; +}; + +} + +#endif // LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp new file mode 100644 index 0000000000..615d11a1f1 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp @@ -0,0 +1,27 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image.h: Implements the rx::Image class, an abstract base class for the +// renderer-specific classes which will define the interface to the underlying +// surfaces or resources. + +#include "libGLESv2/renderer/d3d/ImageD3D.h" + +namespace rx +{ + +ImageD3D::ImageD3D() +{ +} + +ImageD3D *ImageD3D::makeImageD3D(Image *img) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::ImageD3D*, img)); + return static_cast(img); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h new file mode 100644 index 0000000000..242ce5af70 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h @@ -0,0 +1,54 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image.h: Defines the rx::Image class, an abstract base class for the +// renderer-specific classes which will define the interface to the underlying +// surfaces or resources. + +#ifndef LIBGLESV2_RENDERER_IMAGED3D_H_ +#define LIBGLESV2_RENDERER_IMAGED3D_H_ + +#include "common/debug.h" +#include "libGLESv2/renderer/Image.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; +class TextureStorageInterface3D; +class TextureStorageInterface2DArray; + +class ImageD3D : public Image +{ + public: + ImageD3D(); + virtual ~ImageD3D() {}; + + static ImageD3D *makeImageD3D(Image *img); + + 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; + + private: + DISALLOW_COPY_AND_ASSIGN(ImageD3D); +}; + +} + +#endif // LIBGLESV2_RENDERER_IMAGED3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp new file mode 100644 index 0000000000..13e35e09ec --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp @@ -0,0 +1,196 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface +// class with derivations, classes that perform graphics API agnostic index buffer operations. + +#include "libGLESv2/renderer/d3d/IndexBuffer.h" +#include "libGLESv2/renderer/Renderer.h" + +namespace rx +{ + +unsigned int IndexBuffer::mNextSerial = 1; + +IndexBuffer::IndexBuffer() +{ + updateSerial(); +} + +IndexBuffer::~IndexBuffer() +{ +} + +unsigned int IndexBuffer::getSerial() const +{ + return mSerial; +} + +void IndexBuffer::updateSerial() +{ + mSerial = mNextSerial++; +} + + +IndexBufferInterface::IndexBufferInterface(Renderer *renderer, bool dynamic) : mRenderer(renderer) +{ + mIndexBuffer = renderer->createIndexBuffer(); + + mDynamic = dynamic; + mWritePosition = 0; +} + +IndexBufferInterface::~IndexBufferInterface() +{ + if (mIndexBuffer) + { + delete mIndexBuffer; + } +} + +GLenum IndexBufferInterface::getIndexType() const +{ + return mIndexBuffer->getIndexType(); +} + +unsigned int IndexBufferInterface::getBufferSize() const +{ + return mIndexBuffer->getBufferSize(); +} + +unsigned int IndexBufferInterface::getSerial() const +{ + return mIndexBuffer->getSerial(); +} + +bool IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset) +{ + // Protect against integer overflow + if (mWritePosition + size < mWritePosition) + { + return false; + } + + if (!mIndexBuffer->mapBuffer(mWritePosition, size, outMappedMemory)) + { + if (outMappedMemory) + { + *outMappedMemory = NULL; + } + return false; + } + + if (streamOffset) + { + *streamOffset = mWritePosition; + } + + mWritePosition += size; + return true; +} + +bool IndexBufferInterface::unmapBuffer() +{ + return mIndexBuffer->unmapBuffer(); +} + +IndexBuffer * IndexBufferInterface::getIndexBuffer() const +{ + return mIndexBuffer; +} + +unsigned int IndexBufferInterface::getWritePosition() const +{ + return mWritePosition; +} + +void IndexBufferInterface::setWritePosition(unsigned int writePosition) +{ + mWritePosition = writePosition; +} + +bool IndexBufferInterface::discard() +{ + return mIndexBuffer->discard(); +} + +bool IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum indexType) +{ + if (mIndexBuffer->getBufferSize() == 0) + { + return mIndexBuffer->initialize(bufferSize, indexType, mDynamic); + } + else + { + return mIndexBuffer->setSize(bufferSize, indexType); + } +} + +StreamingIndexBufferInterface::StreamingIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, true) +{ +} + +StreamingIndexBufferInterface::~StreamingIndexBufferInterface() +{ +} + +bool StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType) +{ + bool result = true; + unsigned int curBufferSize = getBufferSize(); + unsigned int writePos = getWritePosition(); + if (size > curBufferSize) + { + result = setBufferSize(std::max(size, 2 * curBufferSize), indexType); + setWritePosition(0); + } + else if (writePos + size > curBufferSize || writePos + size < writePos) + { + if (!discard()) + { + return false; + } + setWritePosition(0); + } + + return result; +} + + +StaticIndexBufferInterface::StaticIndexBufferInterface(Renderer *renderer) : IndexBufferInterface(renderer, false) +{ +} + +StaticIndexBufferInterface::~StaticIndexBufferInterface() +{ +} + +bool StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLenum indexType) +{ + unsigned int curSize = getBufferSize(); + if (curSize == 0) + { + return setBufferSize(size, indexType); + } + else if (curSize >= size && indexType == getIndexType()) + { + return true; + } + else + { + ERR("Static index buffers can't be resized"); + UNREACHABLE(); + return false; + } +} + +IndexRangeCache *StaticIndexBufferInterface::getIndexRangeCache() +{ + return &mIndexRangeCache; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h new file mode 100644 index 0000000000..6fb885a1cd --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h @@ -0,0 +1,111 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexBuffer.h: Defines the abstract IndexBuffer class and IndexBufferInterface +// class with derivations, classes that perform graphics API agnostic index buffer operations. + +#ifndef LIBGLESV2_RENDERER_INDEXBUFFER_H_ +#define LIBGLESV2_RENDERER_INDEXBUFFER_H_ + +#include "common/angleutils.h" +#include "libGLESv2/renderer/IndexRangeCache.h" + +namespace rx +{ +class Renderer; + +class IndexBuffer +{ + public: + IndexBuffer(); + virtual ~IndexBuffer(); + + virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) = 0; + + virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) = 0; + virtual bool unmapBuffer() = 0; + + virtual bool discard() = 0; + + virtual GLenum getIndexType() const = 0; + virtual unsigned int getBufferSize() const = 0; + virtual bool setSize(unsigned int bufferSize, GLenum indexType) = 0; + + unsigned int getSerial() const; + + protected: + void updateSerial(); + + private: + DISALLOW_COPY_AND_ASSIGN(IndexBuffer); + + unsigned int mSerial; + static unsigned int mNextSerial; +}; + +class IndexBufferInterface +{ + public: + IndexBufferInterface(Renderer *renderer, bool dynamic); + virtual ~IndexBufferInterface(); + + virtual bool reserveBufferSpace(unsigned int size, GLenum indexType) = 0; + + GLenum getIndexType() const; + unsigned int getBufferSize() const; + + unsigned int getSerial() const; + + bool mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset); + bool unmapBuffer(); + + IndexBuffer *getIndexBuffer() const; + + protected: + unsigned int getWritePosition() const; + void setWritePosition(unsigned int writePosition); + + bool discard(); + + bool setBufferSize(unsigned int bufferSize, GLenum indexType); + + private: + DISALLOW_COPY_AND_ASSIGN(IndexBufferInterface); + + rx::Renderer *const mRenderer; + + IndexBuffer* mIndexBuffer; + + unsigned int mWritePosition; + bool mDynamic; +}; + +class StreamingIndexBufferInterface : public IndexBufferInterface +{ + public: + StreamingIndexBufferInterface(Renderer *renderer); + ~StreamingIndexBufferInterface(); + + virtual bool reserveBufferSpace(unsigned int size, GLenum indexType); +}; + +class StaticIndexBufferInterface : public IndexBufferInterface +{ + public: + explicit StaticIndexBufferInterface(Renderer *renderer); + ~StaticIndexBufferInterface(); + + virtual bool reserveBufferSpace(unsigned int size, GLenum indexType); + + IndexRangeCache *getIndexRangeCache(); + + private: + IndexRangeCache mIndexRangeCache; +}; + +} + +#endif // LIBGLESV2_RENDERER_INDEXBUFFER_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp new file mode 100644 index 0000000000..932524c132 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp @@ -0,0 +1,339 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexDataManager.cpp: Defines the IndexDataManager, a class that +// runs the Buffer translation process for index buffers. + +#include "libGLESv2/renderer/d3d/IndexDataManager.h" +#include "libGLESv2/renderer/d3d/BufferD3D.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) +{ + 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) + { + const GLubyte *in = static_cast(input); + GLushort *out = static_cast(output); + + for (GLsizei i = 0; i < count; i++) + { + out[i] = in[i]; + } + } + else if (type == GL_UNSIGNED_INT) + { + memcpy(output, input, count * sizeof(GLuint)); + } + else if (type == GL_UNSIGNED_SHORT) + { + memcpy(output, input, count * sizeof(GLushort)); + } + else UNREACHABLE(); +} + +template +static void computeRange(const IndexType *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +{ + *minIndex = indices[0]; + *maxIndex = indices[0]; + + for (GLsizei i = 0; i < count; i++) + { + if (*minIndex > indices[i]) *minIndex = indices[i]; + if (*maxIndex < indices[i]) *maxIndex = indices[i]; + } +} + +static void computeRange(GLenum type, const GLvoid *indices, GLsizei count, GLuint *minIndex, GLuint *maxIndex) +{ + if (type == GL_UNSIGNED_BYTE) + { + computeRange(static_cast(indices), count, minIndex, maxIndex); + } + else if (type == GL_UNSIGNED_INT) + { + computeRange(static_cast(indices), count, minIndex, maxIndex); + } + else if (type == GL_UNSIGNED_SHORT) + { + computeRange(static_cast(indices), count, minIndex, maxIndex); + } + else UNREACHABLE(); +} + +GLenum IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buffer *buffer, const GLvoid *indices, TranslatedIndexData *translated) +{ + if (!mStreamingBufferShort) + { + return GL_OUT_OF_MEMORY; + } + + GLenum destinationIndexType = (type == GL_UNSIGNED_INT) ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; + unsigned int offset = 0; + bool alignedOffset = false; + + BufferD3D *storage = NULL; + + 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()); + + switch (type) + { + case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break; + case GL_UNSIGNED_SHORT: alignedOffset = (offset % sizeof(GLushort) == 0); break; + case GL_UNSIGNED_INT: alignedOffset = (offset % sizeof(GLuint) == 0); break; + default: UNREACHABLE(); alignedOffset = false; + } + + 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; + } + + indices = static_cast(storage->getData()) + offset; + } + + StreamingIndexBufferInterface *streamingBuffer = (type == GL_UNSIGNED_INT) ? mStreamingBufferInt : mStreamingBufferShort; + + StaticIndexBufferInterface *staticBuffer = storage ? storage->getStaticIndexBuffer() : NULL; + IndexBufferInterface *indexBuffer = streamingBuffer; + 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)) + { + computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); + storage->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, + translated->maxIndex, 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)) + { + 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); + } + } + else + { + unsigned int convertCount = count; + + if (staticBuffer) + { + if (staticBuffer->getBufferSize() == 0 && alignedOffset) + { + indexBuffer = staticBuffer; + convertCount = storage->getSize() / gl::GetTypeBytes(type); + } + else + { + storage->invalidateStaticData(); + staticBuffer = NULL; + } + } + + if (!indexBuffer) + { + ERR("No valid index buffer."); + return GL_INVALID_OPERATION; + } + + unsigned int indexTypeSize = gl::GetTypeBytes(destinationIndexType); + if (convertCount > std::numeric_limits::max() / indexTypeSize) + { + ERR("Reserving %u indicies of %u bytes each exceeds the maximum buffer size.", convertCount, indexTypeSize); + return GL_OUT_OF_MEMORY; + } + + unsigned int bufferSizeRequired = convertCount * indexTypeSize; + if (!indexBuffer->reserveBufferSpace(bufferSizeRequired, type)) + { + ERR("Failed to reserve %u bytes in an index buffer.", bufferSizeRequired); + return GL_OUT_OF_MEMORY; + } + + void* output = NULL; + if (!indexBuffer->mapBuffer(bufferSizeRequired, &output, &streamOffset)) + { + ERR("Failed to map index buffer."); + return GL_OUT_OF_MEMORY; + } + + convertIndices(type, staticBuffer ? storage->getData() : indices, convertCount, output); + + if (!indexBuffer->unmapBuffer()) + { + ERR("Failed to unmap index buffer."); + return GL_OUT_OF_MEMORY; + } + + computeRange(type, indices, count, &translated->minIndex, &translated->maxIndex); + + if (staticBuffer) + { + streamOffset = (offset / gl::GetTypeBytes(type)) * gl::GetTypeBytes(destinationIndexType); + staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->minIndex, + translated->maxIndex, streamOffset); + } + } + + translated->storage = directStorage ? storage : NULL; + translated->indexBuffer = indexBuffer->getIndexBuffer(); + translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial(); + translated->startIndex = streamOffset / gl::GetTypeBytes(destinationIndexType); + translated->startOffset = streamOffset; + + if (storage) + { + storage->promoteStaticUsage(count * gl::GetTypeBytes(type)); + } + + return GL_NO_ERROR; +} + +StaticIndexBufferInterface *IndexDataManager::getCountingIndices(GLsizei count) +{ + if (count <= 65536) // 16-bit indices + { + const unsigned int spaceNeeded = count * sizeof(unsigned short); + + if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded) + { + delete mCountingBuffer; + mCountingBuffer = new StaticIndexBufferInterface(mRenderer); + mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT); + + void* mappedMemory = NULL; + if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL)) + { + ERR("Failed to map counting buffer."); + return NULL; + } + + unsigned short *data = reinterpret_cast(mappedMemory); + for(int i = 0; i < count; i++) + { + data[i] = i; + } + + if (!mCountingBuffer->unmapBuffer()) + { + ERR("Failed to unmap counting buffer."); + return NULL; + } + } + } + else if (mStreamingBufferInt) // 32-bit indices supported + { + const unsigned int spaceNeeded = count * sizeof(unsigned int); + + if (!mCountingBuffer || mCountingBuffer->getBufferSize() < spaceNeeded) + { + delete mCountingBuffer; + mCountingBuffer = new StaticIndexBufferInterface(mRenderer); + mCountingBuffer->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT); + + void* mappedMemory = NULL; + if (!mCountingBuffer->mapBuffer(spaceNeeded, &mappedMemory, NULL)) + { + ERR("Failed to map counting buffer."); + return NULL; + } + + unsigned int *data = reinterpret_cast(mappedMemory); + for(int i = 0; i < count; i++) + { + data[i] = i; + } + + if (!mCountingBuffer->unmapBuffer()) + { + ERR("Failed to unmap counting buffer."); + return NULL; + } + } + } + else + { + return NULL; + } + + return mCountingBuffer; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h new file mode 100644 index 0000000000..8f981936ea --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h @@ -0,0 +1,66 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexDataManager.h: Defines the IndexDataManager, a class that +// runs the Buffer translation process for index buffers. + +#ifndef LIBGLESV2_INDEXDATAMANAGER_H_ +#define LIBGLESV2_INDEXDATAMANAGER_H_ + +#include "common/angleutils.h" + +namespace +{ + enum { INITIAL_INDEX_BUFFER_SIZE = 4096 * sizeof(GLuint) }; +} + +namespace gl +{ +class Buffer; +} + +namespace rx +{ +class StaticIndexBufferInterface; +class StreamingIndexBufferInterface; +class IndexBuffer; +class BufferD3D; +class Renderer; + +struct TranslatedIndexData +{ + unsigned int minIndex; + unsigned int maxIndex; + unsigned int startIndex; + unsigned int startOffset; // In bytes + + IndexBuffer *indexBuffer; + BufferD3D *storage; + unsigned int serial; +}; + +class IndexDataManager +{ + public: + explicit IndexDataManager(Renderer *renderer); + virtual ~IndexDataManager(); + + GLenum prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated); + StaticIndexBufferInterface *getCountingIndices(GLsizei count); + + private: + DISALLOW_COPY_AND_ASSIGN(IndexDataManager); + + Renderer *const mRenderer; + + StreamingIndexBufferInterface *mStreamingBufferShort; + StreamingIndexBufferInterface *mStreamingBufferInt; + StaticIndexBufferInterface *mCountingBuffer; +}; + +} + +#endif // LIBGLESV2_INDEXDATAMANAGER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp new file mode 100644 index 0000000000..301bbe8d3d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp @@ -0,0 +1,72 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "libGLESv2/renderer/d3d/MemoryBuffer.h" + +#include +#include + +namespace rx +{ + +MemoryBuffer::MemoryBuffer() + : mSize(0), + mData(NULL) +{ +} + +MemoryBuffer::~MemoryBuffer() +{ + free(mData); + mData = NULL; +} + +bool MemoryBuffer::resize(size_t size) +{ + if (size == 0) + { + free(mData); + mData = NULL; + mSize = 0; + } + else + { + uint8_t *newMemory = reinterpret_cast(malloc(sizeof(uint8_t) * size)); + if (newMemory == NULL) + { + return false; + } + + if (mData) + { + // Copy the intersection of the old data and the new data + std::copy(mData, mData + std::min(mSize, size), newMemory); + free(mData); + } + + mData = newMemory; + mSize = size; + } + + return true; +} + +size_t MemoryBuffer::size() const +{ + return mSize; +} + +const uint8_t *MemoryBuffer::data() const +{ + return mData; +} + +uint8_t *MemoryBuffer::data() +{ + return mData; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h new file mode 100644 index 0000000000..2484c07455 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h @@ -0,0 +1,35 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#ifndef LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_ +#define LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_ + +#include +#include + +namespace rx +{ + +class MemoryBuffer +{ + public: + MemoryBuffer(); + ~MemoryBuffer(); + + bool resize(size_t size); + size_t size() const; + + const uint8_t *data() const; + uint8_t *data(); + + private: + size_t mSize; + uint8_t *mData; +}; + +} + +#endif // LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp new file mode 100644 index 0000000000..e725e2fefe --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp @@ -0,0 +1,2550 @@ +#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. +// + +// 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/Buffer.h" +#include "libGLESv2/Framebuffer.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 +{ + +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 IsRenderTargetUsage(GLenum usage) +{ + return (usage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); +} + +TextureD3D::TextureD3D(Renderer *renderer) + : mRenderer(renderer), + mUsage(GL_NONE), + mDirtyImages(true), + mImmutable(false) +{ +} + +TextureD3D::~TextureD3D() +{ +} + +GLint TextureD3D::getBaseLevelWidth() const +{ + const Image *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getWidth() : 0); +} + +GLint TextureD3D::getBaseLevelHeight() const +{ + const Image *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getHeight() : 0); +} + +GLint TextureD3D::getBaseLevelDepth() const +{ + const Image *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getDepth() : 0); +} + +// Note: "base level image" is loosely defined to be any image from the base level, +// where in the base of 2D array textures and cube maps there are several. Don't use +// the base level image for anything except querying texture format and size. +GLenum TextureD3D::getBaseLevelInternalFormat() const +{ + const Image *baseImage = getBaseLevelImage(); + return (baseImage ? baseImage->getInternalFormat() : GL_NONE); +} + +void TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, Image *image) +{ + // No-op + if (image->getWidth() == 0 || image->getHeight() == 0 || image->getDepth() == 0) + { + return; + } + + // We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains. + // From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components. + const void *pixelData = pixels; + + if (unpack.pixelBuffer.id() != 0) + { + // Do a CPU readback here, if we have an unpack buffer bound and the fast GPU path is not supported + gl::Buffer *pixelBuffer = unpack.pixelBuffer.get(); + ptrdiff_t offset = reinterpret_cast(pixels); + // TODO: 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(); + pixelData = static_cast(bufferData) + offset; + } + + if (pixelData != NULL) + { + image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData); + mDirtyImages = true; + } +} + +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) +{ + const void *pixelData = pixels; + + // CPU readback & copy where direct GPU copy is not supported + if (unpack.pixelBuffer.id() != 0) + { + gl::Buffer *pixelBuffer = unpack.pixelBuffer.get(); + unsigned int 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(); + pixelData = static_cast(bufferData) + offset; + } + + if (pixelData != NULL) + { + image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment, type, pixelData); + mDirtyImages = true; + } + + return true; +} + +void TextureD3D::setCompressedImage(GLsizei imageSize, const void *pixels, Image *image) +{ + if (pixels != NULL) + { + image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixels); + mDirtyImages = true; + } +} + +bool TextureD3D::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLsizei imageSize, const void *pixels, Image *image) +{ + if (pixels != NULL) + { + image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixels); + mDirtyImages = true; + } + + return true; +} + +bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat) +{ + return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat); +} + +bool TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea, + GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget) +{ + if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0) + { + return true; + } + + // In order to perform the fast copy through the shader, we must have the right format, and be able + // to create a render target. + ASSERT(mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat)); + + unsigned int offset = reinterpret_cast(pixels); + + return mRenderer->fastCopyBufferToTexture(unpack, offset, destRenderTarget, sizedInternalFormat, type, destArea); +} + +GLint TextureD3D::creationLevels(GLsizei width, GLsizei height, GLsizei depth) const +{ + if ((gl::isPow2(width) && gl::isPow2(height) && gl::isPow2(depth)) || mRenderer->getRendererExtensions().textureNPOT) + { + // Maximum number of levels + return gl::log2(std::max(std::max(width, height), depth)) + 1; + } + else + { + // OpenGL ES 2.0 without GL_OES_texture_npot does not permit NPOT mipmaps. + return 1; + } +} + +int TextureD3D::mipLevels() const +{ + return gl::log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1; +} + + +TextureD3D_2D::TextureD3D_2D(Renderer *renderer) + : TextureD3D(renderer), + Texture2DImpl(), + mTexStorage(NULL) +{ + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + mImageArray[i] = ImageD3D::makeImageD3D(renderer->createImage()); + } +} + +TextureD3D_2D::~TextureD3D_2D() +{ + SafeDelete(mTexStorage); + + 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; +} + +Image *TextureD3D_2D::getImage(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return mImageArray[level]; +} + +void TextureD3D_2D::setUsage(GLenum usage) +{ + mUsage = usage; +} + +void TextureD3D_2D::resetDirty() +{ + mDirtyImages = false; +} + +GLsizei TextureD3D_2D::getWidth(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getWidth(); + else + return 0; +} + +GLsizei TextureD3D_2D::getHeight(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getHeight(); + else + return 0; +} + +GLenum TextureD3D_2D::getInternalFormat(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getInternalFormat(); + else + return GL_NONE; +} + +GLenum TextureD3D_2D::getActualFormat(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getActualFormat(); + else + return GL_NONE; +} + +bool TextureD3D_2D::isDepth(GLint level) const +{ + return gl::GetDepthBits(getInternalFormat(level)) > 0; +} + +void TextureD3D_2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) +{ + GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat + : gl::GetSizedInternalFormat(format, type); + bool fastUnpacked = false; + + // Attempt a fast gpu copy of the pixel data to the surface + if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level)) + { + // Will try to create RT storage if it does not exist + RenderTarget *destRenderTarget = getRenderTarget(level); + gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), 1); + + if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget)) + { + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; + } + } + + if (!fastUnpacked) + { + TextureD3D::setImage(unpack, type, pixels, mImageArray[level]); + } +} + +void TextureD3D_2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const void *pixels) +{ + 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) +{ + bool fastUnpacked = false; + + if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level)) + { + RenderTarget *renderTarget = getRenderTarget(level); + gl::Box destArea(xoffset, yoffset, 0, width, height, 1); + + if (renderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget)) + { + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; + } + } + + if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, mImageArray[level])) + { + 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) +{ + 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) +{ + if (!mImageArray[level]->isRenderableFormat()) + { + mImageArray[level]->copy(0, 0, 0, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + mImageArray[level]->markClean(); + + if (width != 0 && height != 0 && isValidLevel(level)) + { + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(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) +{ + // 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); + + if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) + { + mImageArray[level]->copy(xoffset, yoffset, 0, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + + if (isValidLevel(level)) + { + updateStorageLevel(level); + + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, + gl::GetFormat(getBaseLevelInternalFormat()), + xoffset, yoffset, mTexStorage, level); + } + } +} + +void TextureD3D_2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height) +{ + for (int level = 0; level < levels; level++) + { + GLsizei levelWidth = std::max(1, width >> level); + GLsizei levelHeight = std::max(1, height >> level); + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, levelWidth, levelHeight, 1, true); + } + + for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true); + } + + 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; +} + +void TextureD3D_2D::bindTexImage(egl::Surface *surface) +{ + GLenum internalformat = surface->getFormat(); + + mImageArray[0]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, surface->getWidth(), surface->getHeight(), 1, true); + + if (mTexStorage) + { + SafeDelete(mTexStorage); + } + mTexStorage = new TextureStorageInterface2D(mRenderer, surface->getSwapChain()); + + mDirtyImages = true; +} + +void TextureD3D_2D::releaseTexImage() +{ + if (mTexStorage) + { + SafeDelete(mTexStorage); + } + + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mImageArray[i]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true); + } +} + +void TextureD3D_2D::generateMipmaps() +{ + int levelCount = mipLevels(); + + if (mTexStorage && mTexStorage->isRenderTarget()) + { + for (int level = 1; level < levelCount; level++) + { + mTexStorage->generateMipmap(level); + + mImageArray[level]->markClean(); + } + } + else + { + for (int level = 1; level < levelCount; level++) + { + mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]); + } + } +} + +unsigned int TextureD3D_2D::getRenderTargetSerial(GLint level) +{ + return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level) : 0); +} + +RenderTarget *TextureD3D_2D::getRenderTarget(GLint level) +{ + // 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); +} + +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; +} + +bool TextureD3D_2D::isValidLevel(int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : false); +} + +bool TextureD3D_2D::isLevelComplete(int level) const +{ + if (isImmutable()) + { + return true; + } + + const Image *baseImage = getBaseLevelImage(); + + GLsizei width = baseImage->getWidth(); + GLsizei height = baseImage->getHeight(); + + if (width <= 0 || height <= 0) + { + return false; + } + + // The base image level is complete if the width and height are positive + if (level == 0) + { + return true; + } + + ASSERT(level >= 1 && level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ImageD3D *image = mImageArray[level]; + + if (image->getInternalFormat() != baseImage->getInternalFormat()) + { + return false; + } + + if (image->getWidth() != std::max(1, width >> level)) + { + return false; + } + + if (image->getHeight() != std::max(1, height >> level)) + { + return false; + } + + return true; +} + +// Constructs a native texture resource from the texture images +void TextureD3D_2D::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return; + } + + // do not attempt to create storage for nonexistant data + if (!isLevelComplete(0)) + { + return; + } + + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); + + setCompleteTexStorage(createCompleteStorage(createRenderTarget)); + ASSERT(mTexStorage); + + // flush image data to the storage + updateStorage(); +} + +TextureStorageInterface2D *TextureD3D_2D::createCompleteStorage(bool renderTarget) const +{ + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + + 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); +} + +void TextureD3D_2D::setCompleteTexStorage(TextureStorageInterface2D *newCompleteTexStorage) +{ + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + + if (mTexStorage && mTexStorage->isManaged()) + { + for (int level = 0; level < mTexStorage->getLevelCount(); level++) + { + mImageArray[level]->setManagedSurface(mTexStorage, level); + } + } + + mDirtyImages = true; +} + +void TextureD3D_2D::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int level = 0; level < storageLevels; level++) + { + if (mImageArray[level]->isDirty() && isLevelComplete(level)) + { + updateStorageLevel(level); + } + } +} + +bool TextureD3D_2D::ensureRenderTarget() +{ + initializeStorage(true); + + if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0) + { + ASSERT(mTexStorage); + if (!mTexStorage->isRenderTarget()) + { + TextureStorageInterface2D *newRenderTargetStorage = createCompleteStorage(true); + + if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) + { + delete newRenderTargetStorage; + return gl::error(GL_OUT_OF_MEMORY, false); + } + + setCompleteTexStorage(newRenderTargetStorage); + } + } + + return (mTexStorage && mTexStorage->isRenderTarget()); +} + +TextureStorageInterface *TextureD3D_2D::getBaseLevelStorage() +{ + return mTexStorage; +} + +const ImageD3D *TextureD3D_2D::getBaseLevelImage() const +{ + return mImageArray[0]; +} + +void TextureD3D_2D::updateStorageLevel(int level) +{ + ASSERT(level <= (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ASSERT(isLevelComplete(level)); + + if (mImageArray[level]->isDirty()) + { + commitRect(level, 0, 0, getWidth(level), getHeight(level)); + } +} + +void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getBaseLevelWidth() >> level); + const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, width, height, 1, false); + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + width != storageWidth || + height != storageHeight || + internalformat != storageFormat) // Discard mismatched storage + { + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mImageArray[i]->markDirty(); + } + + SafeDelete(mTexStorage); + mDirtyImages = true; + } + } +} + +void TextureD3D_2D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + if (isValidLevel(level)) + { + ImageD3D *image = mImageArray[level]; + if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, width, height)) + { + image->markClean(); + } + } +} + + +TextureD3D_Cube::TextureD3D_Cube(Renderer *renderer) + : TextureCubeImpl(), + TextureD3D(renderer), + mTexStorage(NULL) +{ + for (int i = 0; i < 6; i++) + { + for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) + { + mImageArray[i][j] = ImageD3D::makeImageD3D(renderer->createImage()); + } + } +} + +TextureD3D_Cube::~TextureD3D_Cube() +{ + SafeDelete(mTexStorage); + + for (int i = 0; i < 6; i++) + { + for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j) + { + 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; +} + +Image *TextureD3D_Cube::getImage(GLenum target, int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return mImageArray[targetToIndex(target)][level]; +} + +void TextureD3D_Cube::setUsage(GLenum usage) +{ + mUsage = usage; +} + +void TextureD3D_Cube::resetDirty() +{ + mDirtyImages = false; +} + +GLenum TextureD3D_Cube::getInternalFormat(GLenum target, GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[targetToIndex(target)][level]->getInternalFormat(); + else + return GL_NONE; +} + +bool TextureD3D_Cube::isDepth(GLenum target, GLint level) const +{ + return gl::GetDepthBits(getInternalFormat(target, level)) > 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) +{ + GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat + : gl::GetSizedInternalFormat(format, 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) +{ + // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly + int faceIndex = targetToIndex(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) +{ + int faceIndex = targetToIndex(target); + if (TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, mImageArray[faceIndex][level])) + { + 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) +{ + int faceIndex = targetToIndex(target); + if (TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, pixels, mImageArray[faceIndex][level])) + { + commitRect(faceIndex, level, xoffset, yoffset, width, height); + } +} + +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); + redefineImage(faceIndex, level, sizedInternalFormat, width, height); + + if (!mImageArray[faceIndex][level]->isRenderableFormat()) + { + mImageArray[faceIndex][level]->copy(0, 0, 0, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + mImageArray[faceIndex][level]->markClean(); + + ASSERT(width == height); + + if (width > 0 && isValidFaceLevel(faceIndex, level)) + { + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(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); + + // 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 + // rely on the "getBaseLevel*" methods reliably otherwise. + bool canCreateRenderTarget = isFaceLevelComplete(faceIndex, level) && isCubeComplete(); + + if (!mImageArray[faceIndex][level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) + { + mImageArray[faceIndex][level]->copy(0, 0, 0, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + + if (isValidFaceLevel(faceIndex, level)) + { + updateStorageFaceLevel(faceIndex, level); + + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, gl::GetFormat(getBaseLevelInternalFormat()), + xoffset, yoffset, mTexStorage, target, level); + } + } +} + +void TextureD3D_Cube::storage(GLsizei levels, GLenum internalformat, GLsizei size) +{ + for (int level = 0; level < levels; level++) + { + GLsizei mipSize = std::max(1, size >> level); + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, mipSize, mipSize, 1, true); + } + } + + for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, GL_NONE, 0, 0, 0, true); + } + } + + 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; +} + +// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81. +bool TextureD3D_Cube::isCubeComplete() const +{ + int baseWidth = getBaseLevelWidth(); + int baseHeight = getBaseLevelHeight(); + GLenum baseFormat = getBaseLevelInternalFormat(); + + if (baseWidth <= 0 || baseWidth != baseHeight) + { + return false; + } + + for (int faceIndex = 1; faceIndex < 6; faceIndex++) + { + const ImageD3D &faceBaseImage = *mImageArray[faceIndex][0]; + + if (faceBaseImage.getWidth() != baseWidth || + faceBaseImage.getHeight() != baseHeight || + faceBaseImage.getInternalFormat() != baseFormat ) + { + return false; + } + } + + return true; +} + +void TextureD3D_Cube::generateMipmaps() +{ + // Purge array levels 1 through q and reset them to represent the generated mipmap levels. + int levelCount = mipLevels(); + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 1; level < levelCount; level++) + { + int faceLevelSize = (std::max(mImageArray[faceIndex][0]->getWidth() >> level, 1)); + redefineImage(faceIndex, level, mImageArray[faceIndex][0]->getInternalFormat(), faceLevelSize, faceLevelSize); + } + } + + if (mTexStorage && mTexStorage->isRenderTarget()) + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 1; level < levelCount; level++) + { + mTexStorage->generateMipmap(faceIndex, level); + + mImageArray[faceIndex][level]->markClean(); + } + } + } + else + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 1; level < levelCount; level++) + { + mRenderer->generateMipmap(mImageArray[faceIndex][level], mImageArray[faceIndex][level - 1]); + } + } + } +} + +unsigned int TextureD3D_Cube::getRenderTargetSerial(GLenum target, GLint level) +{ + 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); +} + +RenderTarget *TextureD3D_Cube::getDepthStencil(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 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; +} + +void TextureD3D_Cube::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return; + } + + // do not attempt to create storage for nonexistant data + if (!isFaceLevelComplete(0, 0)) + { + return; + } + + bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage)); + + setCompleteTexStorage(createCompleteStorage(createRenderTarget)); + ASSERT(mTexStorage); + + // flush image data to the storage + updateStorage(); +} + +TextureStorageInterfaceCube *TextureD3D_Cube::createCompleteStorage(bool renderTarget) const +{ + GLsizei size = getBaseLevelWidth(); + + ASSERT(size > 0); + + // use existing storage level count, when previously specified by TexStorage*D + GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1)); + + return new TextureStorageInterfaceCube(mRenderer, getBaseLevelInternalFormat(), renderTarget, size, levels); +} + +void TextureD3D_Cube::setCompleteTexStorage(TextureStorageInterfaceCube *newCompleteTexStorage) +{ + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + + if (mTexStorage && mTexStorage->isManaged()) + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + for (int level = 0; level < mTexStorage->getLevelCount(); level++) + { + mImageArray[faceIndex][level]->setManagedSurface(mTexStorage, faceIndex, level); + } + } + } + + mDirtyImages = true; +} + +void TextureD3D_Cube::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int face = 0; face < 6; face++) + { + for (int level = 0; level < storageLevels; level++) + { + if (mImageArray[face][level]->isDirty() && isFaceLevelComplete(face, level)) + { + updateStorageFaceLevel(face, level); + } + } + } +} + +bool TextureD3D_Cube::ensureRenderTarget() +{ + initializeStorage(true); + + if (getBaseLevelWidth() > 0) + { + ASSERT(mTexStorage); + if (!mTexStorage->isRenderTarget()) + { + TextureStorageInterfaceCube *newRenderTargetStorage = createCompleteStorage(true); + + if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) + { + delete newRenderTargetStorage; + return gl::error(GL_OUT_OF_MEMORY, false); + } + + setCompleteTexStorage(newRenderTargetStorage); + } + } + + return (mTexStorage && mTexStorage->isRenderTarget()); +} + +TextureStorageInterface *TextureD3D_Cube::getBaseLevelStorage() +{ + return mTexStorage; +} + +const ImageD3D *TextureD3D_Cube::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 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); + + if (isImmutable()) + { + return true; + } + + int baseSize = getBaseLevelWidth(); + + if (baseSize <= 0) + { + return false; + } + + // "isCubeComplete" checks for base level completeness and we must call that + // to determine if any face at level 0 is complete. We omit that check here + // to avoid re-checking cube-completeness for every face at level 0. + if (level == 0) + { + return true; + } + + // Check that non-zero levels are consistent with the base level. + const ImageD3D *faceLevelImage = mImageArray[faceIndex][level]; + + if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat()) + { + return false; + } + + if (faceLevelImage->getWidth() != std::max(1, baseSize >> level)) + { + return false; + } + + return true; +} + +void TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level) +{ + ASSERT(level >= 0 && faceIndex < 6 && level < (int)ArraySize(mImageArray[faceIndex]) && mImageArray[faceIndex][level] != NULL); + ImageD3D *image = mImageArray[faceIndex][level]; + + if (image->isDirty()) + { + commitRect(faceIndex, level, 0, 0, image->getWidth(), image->getHeight()); + } +} + +void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getBaseLevelWidth() >> level); + const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, width, height, 1, false); + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + width != storageWidth || + height != storageHeight || + internalformat != storageFormat) // Discard mismatched storage + { + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + for (int faceIndex = 0; faceIndex < 6; faceIndex++) + { + mImageArray[faceIndex][level]->markDirty(); + } + } + + SafeDelete(mTexStorage); + + mDirtyImages = true; + } + } +} + +void TextureD3D_Cube::commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + if (isValidFaceLevel(faceIndex, level)) + { + ImageD3D *image = mImageArray[faceIndex][level]; + if (image->copyToStorage(mTexStorage, faceIndex, level, xoffset, yoffset, width, height)) + image->markClean(); + } +} + + +TextureD3D_3D::TextureD3D_3D(Renderer *renderer) + : Texture3DImpl(), + TextureD3D(renderer), + mTexStorage(NULL) +{ + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i) + { + mImageArray[i] = ImageD3D::makeImageD3D(renderer->createImage()); + } +} + +TextureD3D_3D::~TextureD3D_3D() +{ + SafeDelete(mTexStorage); + + 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; +} + +Image *TextureD3D_3D::getImage(int level) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + return mImageArray[level]; +} + +void TextureD3D_3D::setUsage(GLenum usage) +{ + mUsage = usage; +} + +void TextureD3D_3D::resetDirty() +{ + mDirtyImages = false; +} + +GLsizei TextureD3D_3D::getWidth(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getWidth(); + else + return 0; +} + +GLsizei TextureD3D_3D::getHeight(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getHeight(); + else + return 0; +} + +GLsizei TextureD3D_3D::getDepth(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getDepth(); + else + return 0; +} + +GLenum TextureD3D_3D::getInternalFormat(GLint level) const +{ + if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) + return mImageArray[level]->getInternalFormat(); + else + return GL_NONE; +} + +bool TextureD3D_3D::isDepth(GLint level) const +{ + return gl::GetDepthBits(getInternalFormat(level)) > 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) +{ + GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat + : gl::GetSizedInternalFormat(format, type); + redefineImage(level, sizedInternalFormat, width, height, depth); + + bool fastUnpacked = false; + + // Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer + if (isFastUnpackable(unpack, sizedInternalFormat)) + { + // Will try to create RT storage if it does not exist + RenderTarget *destRenderTarget = getRenderTarget(level); + gl::Box destArea(0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); + + if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, sizedInternalFormat, type, destRenderTarget)) + { + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; + } + } + + if (!fastUnpacked) + { + TextureD3D::setImage(unpack, type, pixels, mImageArray[level]); + } +} + +void TextureD3D_3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, 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, 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) +{ + bool fastUnpacked = false; + + // 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); + gl::Box destArea(xoffset, yoffset, zoffset, width, height, depth); + + if (destRenderTarget && fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget)) + { + // Ensure we don't overwrite our newly initialized data + mImageArray[level]->markClean(); + + fastUnpacked = true; + } + } + + if (!fastUnpacked && TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels, mImageArray[level])) + { + 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) +{ + 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::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + // 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); + + if (!mImageArray[level]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) + { + mImageArray[level]->copy(xoffset, yoffset, zoffset, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + + if (isValidLevel(level)) + { + updateStorageLevel(level); + + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, + gl::GetFormat(getBaseLevelInternalFormat()), + xoffset, yoffset, zoffset, mTexStorage, level); + } + } +} + +void TextureD3D_3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + for (int level = 0; level < levels; level++) + { + GLsizei levelWidth = std::max(1, width >> level); + GLsizei levelHeight = std::max(1, height >> level); + GLsizei levelDepth = std::max(1, depth >> level); + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, levelWidth, levelHeight, levelDepth, true); + } + + for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, GL_NONE, 0, 0, 0, true); + } + + mImmutable = true; + + setCompleteTexStorage(new TextureStorageInterface3D(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, depth, levels)); +} + +bool TextureD3D_3D::isSamplerComplete(const gl::SamplerState &samplerState) const +{ + 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; +} + +bool TextureD3D_3D::isMipmapComplete() const +{ + int levelCount = mipLevels(); + + for (int level = 0; level < levelCount; level++) + { + if (!isLevelComplete(level)) + { + return false; + } + } + + return true; +} + +void TextureD3D_3D::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), + std::max(getBaseLevelDepth() >> level, 1)); + } + + if (mTexStorage && mTexStorage->isRenderTarget()) + { + for (int level = 1; level < levelCount; level++) + { + mTexStorage->generateMipmap(level); + + mImageArray[level]->markClean(); + } + } + else + { + for (int level = 1; level < levelCount; level++) + { + mRenderer->generateMipmap(mImageArray[level], mImageArray[level - 1]); + } + } +} + +unsigned int TextureD3D_3D::getRenderTargetSerial(GLint level, GLint layer) +{ + return (ensureRenderTarget() ? mTexStorage->getRenderTargetSerial(level, layer) : 0); +} + +RenderTarget *TextureD3D_3D::getRenderTarget(GLint level) +{ + // 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); +} + +RenderTarget *TextureD3D_3D::getRenderTarget(GLint level, GLint layer) +{ + // ensure the underlying texture is created + if (!ensureRenderTarget()) + { + 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; + } + + updateStorageLevel(level); + + // ensure this is a depth texture + if (!isDepth(level)) + { + return NULL; + } + + return mTexStorage->getRenderTarget(level, layer); +} + +void TextureD3D_3D::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return; + } + + // do not attempt to create storage for nonexistant data + if (!isLevelComplete(0)) + { + return; + } + + bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); + + setCompleteTexStorage(createCompleteStorage(createRenderTarget)); + ASSERT(mTexStorage); + + // flush image data to the storage + updateStorage(); +} + +TextureStorageInterface3D *TextureD3D_3D::createCompleteStorage(bool renderTarget) const +{ + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getBaseLevelDepth(); + + 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); +} + +void TextureD3D_3D::setCompleteTexStorage(TextureStorageInterface3D *newCompleteTexStorage) +{ + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + mDirtyImages = true; + + // We do not support managed 3D storage, as that is D3D9/ES2-only + ASSERT(!mTexStorage->isManaged()); +} + +void TextureD3D_3D::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int level = 0; level < storageLevels; level++) + { + if (mImageArray[level]->isDirty() && isLevelComplete(level)) + { + updateStorageLevel(level); + } + } +} + +bool TextureD3D_3D::ensureRenderTarget() +{ + initializeStorage(true); + + if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getBaseLevelDepth() > 0) + { + ASSERT(mTexStorage); + if (!mTexStorage->isRenderTarget()) + { + TextureStorageInterface3D *newRenderTargetStorage = createCompleteStorage(true); + + if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) + { + delete newRenderTargetStorage; + return gl::error(GL_OUT_OF_MEMORY, false); + } + + setCompleteTexStorage(newRenderTargetStorage); + } + } + + return (mTexStorage && mTexStorage->isRenderTarget()); +} + +TextureStorageInterface *TextureD3D_3D::getBaseLevelStorage() +{ + return mTexStorage; +} + +const ImageD3D *TextureD3D_3D::getBaseLevelImage() const +{ + return mImageArray[0]; +} + +bool TextureD3D_3D::isValidLevel(int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); +} + +bool TextureD3D_3D::isLevelComplete(int level) const +{ + ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + + if (isImmutable()) + { + return true; + } + + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getBaseLevelDepth(); + + if (width <= 0 || height <= 0 || depth <= 0) + { + return false; + } + + if (level == 0) + { + return true; + } + + ImageD3D *levelImage = mImageArray[level]; + + if (levelImage->getInternalFormat() != getBaseLevelInternalFormat()) + { + return false; + } + + if (levelImage->getWidth() != std::max(1, width >> level)) + { + return false; + } + + if (levelImage->getHeight() != std::max(1, height >> level)) + { + return false; + } + + if (levelImage->getDepth() != std::max(1, depth >> level)) + { + return false; + } + + return true; +} + +void TextureD3D_3D::updateStorageLevel(int level) +{ + ASSERT(level >= 0 && level < (int)ArraySize(mImageArray) && mImageArray[level] != NULL); + ASSERT(isLevelComplete(level)); + + if (mImageArray[level]->isDirty()) + { + commitRect(level, 0, 0, 0, getWidth(level), getHeight(level), getDepth(level)); + } +} + +void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getBaseLevelWidth() >> level); + const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + const int storageDepth = std::max(1, getBaseLevelDepth() >> level); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, width, height, depth, false); + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + width != storageWidth || + height != storageHeight || + depth != storageDepth || + internalformat != storageFormat) // Discard mismatched storage + { + for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mImageArray[i]->markDirty(); + } + + SafeDelete(mTexStorage); + mDirtyImages = true; + } + } +} + +void TextureD3D_3D::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) +{ + if (isValidLevel(level)) + { + ImageD3D *image = mImageArray[level]; + if (image->copyToStorage(mTexStorage, level, xoffset, yoffset, zoffset, width, height, depth)) + { + image->markClean(); + } + } +} + + +TextureD3D_2DArray::TextureD3D_2DArray(Renderer *renderer) + : Texture2DArrayImpl(), + TextureD3D(renderer), + mTexStorage(NULL) +{ + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level) + { + mLayerCounts[level] = 0; + mImageArray[level] = NULL; + } +} + +TextureD3D_2DArray::~TextureD3D_2DArray() +{ + SafeDelete(mTexStorage); + + 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; +} + +Image *TextureD3D_2DArray::getImage(int level, int layer) const +{ + ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS); + ASSERT(layer < mLayerCounts[level]); + 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) +{ + mUsage = usage; +} + +void TextureD3D_2DArray::resetDirty() +{ + mDirtyImages = false; +} + +GLsizei TextureD3D_2DArray::getWidth(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getWidth() : 0; +} + +GLsizei TextureD3D_2DArray::getHeight(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getHeight() : 0; +} + +GLsizei TextureD3D_2DArray::getLayers(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mLayerCounts[level] : 0; +} + +GLenum TextureD3D_2DArray::getInternalFormat(GLint level) const +{ + return (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS && mLayerCounts[level] > 0) ? mImageArray[level][0]->getInternalFormat() : GL_NONE; +} + +bool TextureD3D_2DArray::isDepth(GLint level) const +{ + return gl::GetDepthBits(getInternalFormat(level)) > 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) +{ + GLenum sizedInternalFormat = gl::IsSizedInternalFormat(internalFormat) ? internalFormat + : gl::GetSizedInternalFormat(format, type); + redefineImage(level, sizedInternalFormat, width, height, depth); + + GLsizei inputDepthPitch = gl::GetDepthPitch(sizedInternalFormat, type, width, height, unpack.alignment); + + for (int i = 0; i < depth; i++) + { + const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; + TextureD3D::setImage(unpack, type, layerPixels, mImageArray[level][i]); + } +} + +void TextureD3D_2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, 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, depth); + + GLsizei inputDepthPitch = gl::GetDepthPitch(format, GL_UNSIGNED_BYTE, width, height, 1); + + for (int i = 0; i < depth; i++) + { + const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; + TextureD3D::setCompressedImage(imageSize, layerPixels, mImageArray[level][i]); + } +} + +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) +{ + GLenum internalformat = getInternalFormat(level); + GLsizei inputDepthPitch = gl::GetDepthPitch(internalformat, 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])) + { + 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) +{ + GLsizei inputDepthPitch = gl::GetDepthPitch(format, GL_UNSIGNED_BYTE, width, height, 1); + + for (int i = 0; i < depth; i++) + { + int layer = zoffset + i; + const void *layerPixels = pixels ? (reinterpret_cast(pixels) + (inputDepthPitch * i)) : NULL; + + if (TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, layerPixels, mImageArray[level][layer])) + { + commitRect(level, xoffset, yoffset, layer, width, height); + } + } +} + +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) +{ + // 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); + + if (!mImageArray[level][0]->isRenderableFormat() || (!mTexStorage && !canCreateRenderTarget)) + { + mImageArray[level][zoffset]->copy(xoffset, yoffset, 0, x, y, width, height, source); + mDirtyImages = true; + } + else + { + ensureRenderTarget(); + + if (isValidLevel(level)) + { + updateStorageLevel(level); + + gl::Rectangle sourceRect; + sourceRect.x = x; + sourceRect.width = width; + sourceRect.y = y; + sourceRect.height = height; + + mRenderer->copyImage(source, sourceRect, gl::GetFormat(getInternalFormat(0)), + xoffset, yoffset, zoffset, mTexStorage, level); + } + } +} + +void TextureD3D_2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + deleteImages(); + + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + GLsizei levelWidth = std::max(1, width >> level); + GLsizei levelHeight = std::max(1, height >> level); + + mLayerCounts[level] = (level < levels ? depth : 0); + + if (mLayerCounts[level] > 0) + { + // Create new images for this level + mImageArray[level] = new ImageD3D*[mLayerCounts[level]]; + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer] = ImageD3D::makeImageD3D(mRenderer->createImage()); + mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, levelWidth, + levelHeight, 1, true); + } + } + } + + mImmutable = true; + setCompleteTexStorage(new TextureStorageInterface2DArray(mRenderer, internalformat, IsRenderTargetUsage(mUsage), width, height, depth, levels)); +} + +bool TextureD3D_2DArray::isSamplerComplete(const gl::SamplerState &samplerState) const +{ + 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; +} + +bool TextureD3D_2DArray::isMipmapComplete() const +{ + int levelCount = mipLevels(); + + for (int level = 1; level < levelCount; level++) + { + if (!isLevelComplete(level)) + { + return false; + } + } + + return true; +} + +void TextureD3D_2DArray::generateMipmaps() +{ + int baseWidth = getBaseLevelWidth(); + int baseHeight = getBaseLevelHeight(); + int baseDepth = getBaseLevelDepth(); + GLenum baseFormat = getBaseLevelInternalFormat(); + + // Purge array levels 1 through q and reset them to represent the generated mipmap levels. + int levelCount = mipLevels(); + for (int level = 1; level < levelCount; level++) + { + redefineImage(level, baseFormat, std::max(baseWidth >> level, 1), std::max(baseHeight >> level, 1), baseDepth); + } + + if (mTexStorage && mTexStorage->isRenderTarget()) + { + for (int level = 1; level < levelCount; level++) + { + mTexStorage->generateMipmap(level); + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer]->markClean(); + } + } + } + else + { + for (int level = 1; level < levelCount; level++) + { + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mRenderer->generateMipmap(mImageArray[level][layer], mImageArray[level - 1][layer]); + } + } + } +} + +unsigned int TextureD3D_2DArray::getRenderTargetSerial(GLint level, GLint layer) +{ + 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); +} + +RenderTarget *TextureD3D_2DArray::getDepthStencil(GLint level, GLint layer) +{ + // ensure the underlying texture is created + if (!ensureRenderTarget()) + { + return NULL; + } + + updateStorageLevel(level); + + // ensure this is a depth texture + if (!isDepth(level)) + { + return NULL; + } + + return mTexStorage->getRenderTarget(level, layer); +} + +void TextureD3D_2DArray::initializeStorage(bool renderTarget) +{ + // Only initialize the first time this texture is used as a render target or shader resource + if (mTexStorage) + { + return; + } + + // do not attempt to create storage for nonexistant data + if (!isLevelComplete(0)) + { + return; + } + + bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE); + + setCompleteTexStorage(createCompleteStorage(createRenderTarget)); + ASSERT(mTexStorage); + + // flush image data to the storage + updateStorage(); +} + +TextureStorageInterface2DArray *TextureD3D_2DArray::createCompleteStorage(bool renderTarget) const +{ + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei depth = getLayers(0); + + 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); +} + +void TextureD3D_2DArray::setCompleteTexStorage(TextureStorageInterface2DArray *newCompleteTexStorage) +{ + SafeDelete(mTexStorage); + mTexStorage = newCompleteTexStorage; + mDirtyImages = true; + + // We do not support managed 2D array storage, as managed storage is ES2/D3D9 only + ASSERT(!mTexStorage->isManaged()); +} + +void TextureD3D_2DArray::updateStorage() +{ + ASSERT(mTexStorage != NULL); + GLint storageLevels = mTexStorage->getLevelCount(); + for (int level = 0; level < storageLevels; level++) + { + if (isLevelComplete(level)) + { + updateStorageLevel(level); + } + } +} + +bool TextureD3D_2DArray::ensureRenderTarget() +{ + initializeStorage(true); + + if (getBaseLevelWidth() > 0 && getBaseLevelHeight() > 0 && getLayers(0) > 0) + { + ASSERT(mTexStorage); + if (!mTexStorage->isRenderTarget()) + { + TextureStorageInterface2DArray *newRenderTargetStorage = createCompleteStorage(true); + + if (!mRenderer->copyToRenderTarget(newRenderTargetStorage, mTexStorage)) + { + delete newRenderTargetStorage; + return gl::error(GL_OUT_OF_MEMORY, false); + } + + setCompleteTexStorage(newRenderTargetStorage); + } + } + + return (mTexStorage && mTexStorage->isRenderTarget()); +} + +const ImageD3D *TextureD3D_2DArray::getBaseLevelImage() const +{ + return (mLayerCounts[0] > 0 ? mImageArray[0][0] : NULL); +} + +TextureStorageInterface *TextureD3D_2DArray::getBaseLevelStorage() +{ + return mTexStorage; +} + +bool TextureD3D_2DArray::isValidLevel(int level) const +{ + return (mTexStorage ? (level >= 0 && level < mTexStorage->getLevelCount()) : 0); +} + +bool TextureD3D_2DArray::isLevelComplete(int level) const +{ + ASSERT(level >= 0 && level < (int)ArraySize(mImageArray)); + + if (isImmutable()) + { + return true; + } + + GLsizei width = getBaseLevelWidth(); + GLsizei height = getBaseLevelHeight(); + GLsizei layers = 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; +} + +void TextureD3D_2DArray::updateStorageLevel(int level) +{ + ASSERT(level >= 0 && level < (int)ArraySize(mLayerCounts)); + ASSERT(isLevelComplete(level)); + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + ASSERT(mImageArray[level] != NULL && mImageArray[level][layer] != NULL); + if (mImageArray[level][layer]->isDirty()) + { + commitRect(level, 0, 0, layer, getWidth(level), getHeight(level)); + } + } +} + +void TextureD3D_2DArray::deleteImages() +{ + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++level) + { + for (int layer = 0; layer < mLayerCounts[level]; ++layer) + { + delete mImageArray[level][layer]; + } + delete[] mImageArray[level]; + mImageArray[level] = NULL; + mLayerCounts[level] = 0; + } +} + +void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) +{ + // If there currently is a corresponding storage texture image, it has these parameters + const int storageWidth = std::max(1, getBaseLevelWidth() >> level); + const int storageHeight = std::max(1, getBaseLevelHeight() >> level); + const int storageDepth = getLayers(0); + const GLenum storageFormat = getBaseLevelInternalFormat(); + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + delete mImageArray[level][layer]; + } + delete[] mImageArray[level]; + mImageArray[level] = NULL; + mLayerCounts[level] = depth; + + if (depth > 0) + { + mImageArray[level] = new ImageD3D*[depth](); + + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer] = ImageD3D::makeImageD3D(mRenderer->createImage()); + mImageArray[level][layer]->redefine(mRenderer, GL_TEXTURE_2D_ARRAY, internalformat, width, height, 1, false); + } + } + + if (mTexStorage) + { + const int storageLevels = mTexStorage->getLevelCount(); + + if ((level >= storageLevels && storageLevels != 0) || + width != storageWidth || + height != storageHeight || + depth != storageDepth || + internalformat != storageFormat) // Discard mismatched storage + { + for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + for (int layer = 0; layer < mLayerCounts[level]; layer++) + { + mImageArray[level][layer]->markDirty(); + } + } + + delete mTexStorage; + mTexStorage = NULL; + mDirtyImages = true; + } + } +} + +void TextureD3D_2DArray::commitRect(GLint level, GLint xoffset, GLint yoffset, GLint layerTarget, GLsizei width, GLsizei height) +{ + if (isValidLevel(level) && layerTarget < getLayers(level)) + { + ImageD3D *image = mImageArray[level][layerTarget]; + if (image->copyToStorage(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 new file mode 100644 index 0000000000..4a1737a9c4 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h @@ -0,0 +1,343 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureD3D.h: Implementations of the Texture interfaces shared betweeen the D3D backends. + +#ifndef LIBGLESV2_RENDERER_TEXTURED3D_H_ +#define LIBGLESV2_RENDERER_TEXTURED3D_H_ + +#include "libGLESv2/renderer/TextureImpl.h" +#include "libGLESv2/angletypes.h" +#include "libGLESv2/constants.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ + +class Image; +class ImageD3D; +class Renderer; +class TextureStorageInterface; +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; +class TextureStorageInterface3D; +class TextureStorageInterface2DArray; + +bool IsMipmapFiltered(const gl::SamplerState &samplerState); + +class TextureD3D +{ + public: + TextureD3D(Renderer *renderer); + virtual ~TextureD3D(); + + GLint getBaseLevelWidth() const; + GLint getBaseLevelHeight() const; + GLint getBaseLevelDepth() const; + GLenum getBaseLevelInternalFormat() const; + + bool isImmutable() const { return mImmutable; } + + 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); + 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); + + GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const; + int mipLevels() const; + + Renderer *mRenderer; + + GLenum mUsage; + + bool mDirtyImages; + + bool mImmutable; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureD3D); + + virtual TextureStorageInterface *getBaseLevelStorage() = 0; + virtual const ImageD3D *getBaseLevelImage() const = 0; +}; + +class TextureD3D_2D : public Texture2DImpl, 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(); + + GLsizei getWidth(GLint level) const; + GLsizei getHeight(GLint level) const; + GLenum getInternalFormat(GLint level) const; + GLenum getActualFormat(GLint level) const; + bool isDepth(GLint level) const; + + virtual 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 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 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); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureD3D_2D); + + void initializeStorage(bool renderTarget); + TextureStorageInterface2D *createCompleteStorage(bool renderTarget) const; + void setCompleteTexStorage(TextureStorageInterface2D *newCompleteTexStorage); + + void updateStorage(); + bool ensureRenderTarget(); + virtual TextureStorageInterface *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 commitRect(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + TextureStorageInterface2D *mTexStorage; + ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureD3D_Cube : public TextureCubeImpl, 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 void setUsage(GLenum usage); + virtual bool hasDirtyImages() const { return mDirtyImages; } + virtual void resetDirty(); + + GLenum getInternalFormat(GLenum target, GLint level) const; + bool isDepth(GLenum target, GLint level) 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 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 bool isSamplerComplete(const gl::SamplerState &samplerState) const; + virtual bool isCubeComplete() const; + + 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); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureD3D_Cube); + + void initializeStorage(bool renderTarget); + TextureStorageInterfaceCube *createCompleteStorage(bool renderTarget) const; + void setCompleteTexStorage(TextureStorageInterfaceCube *newCompleteTexStorage); + + void updateStorage(); + bool ensureRenderTarget(); + virtual TextureStorageInterface *getBaseLevelStorage(); + virtual const ImageD3D *getBaseLevelImage() const; + + bool isMipmapCubeComplete() const; + bool isValidFaceLevel(int faceIndex, int level) const; + bool isFaceLevelComplete(int faceIndex, int level) const; + void updateStorageFaceLevel(int faceIndex, int level); + + void redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height); + void commitRect(int faceIndex, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + TextureStorageInterfaceCube *mTexStorage; +}; + +class TextureD3D_3D : public Texture3DImpl, 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(); + + GLsizei getWidth(GLint level) const; + GLsizei getHeight(GLint level) const; + GLsizei getDepth(GLint level) const; + GLenum getInternalFormat(GLint level) const; + bool isDepth(GLint level) const; + + virtual 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 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 bool isSamplerComplete(const gl::SamplerState &samplerState) const; + virtual bool isMipmapComplete() const; + + 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); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureD3D_3D); + + virtual void initializeStorage(bool renderTarget); + TextureStorageInterface3D *createCompleteStorage(bool renderTarget) const; + void setCompleteTexStorage(TextureStorageInterface3D *newCompleteTexStorage); + + void updateStorage(); + bool ensureRenderTarget(); + virtual TextureStorageInterface *getBaseLevelStorage(); + virtual const ImageD3D *getBaseLevelImage() const; + + bool isValidLevel(int level) const; + bool isLevelComplete(int level) const; + void updateStorageLevel(int level); + + void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + void commitRect(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth); + + ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + TextureStorageInterface3D *mTexStorage; +}; + +class TextureD3D_2DArray : public Texture2DArrayImpl, 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 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 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 bool isSamplerComplete(const gl::SamplerState &samplerState) const; + virtual bool isMipmapComplete() const; + + 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); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureD3D_2DArray); + + virtual void initializeStorage(bool renderTarget); + TextureStorageInterface2DArray *createCompleteStorage(bool renderTarget) const; + void setCompleteTexStorage(TextureStorageInterface2DArray *newCompleteTexStorage); + + void updateStorage(); + bool ensureRenderTarget(); + virtual TextureStorageInterface *getBaseLevelStorage(); + virtual const ImageD3D *getBaseLevelImage() const; + + bool isValidLevel(int level) const; + bool isLevelComplete(int level) const; + void updateStorageLevel(int level); + + void deleteImages(); + void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth); + void commitRect(GLint level, GLint xoffset, GLint yoffset, GLint layerTarget, GLsizei width, GLsizei height); + + // Storing images as an array of single depth textures since D3D11 treats each array level of a + // Texture2D object as a separate subresource. Each layer would have to be looped over + // to update all the texture layers since they cannot all be updated at once and it makes the most + // sense for the Image class to not have to worry about layer subresource as well as mip subresources. + GLsizei mLayerCounts[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + ImageD3D **mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + TextureStorageInterface2DArray *mTexStorage; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTURED3D_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp new file mode 100644 index 0000000000..846586984c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp @@ -0,0 +1,181 @@ +#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. + +#include "libGLESv2/renderer/d3d/TextureStorage.h" +#include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/Texture.h" + +#include "common/debug.h" +#include "common/mathutil.h" + +namespace rx +{ +unsigned int TextureStorageInterface::mCurrentTextureSerial = 1; + +TextureStorageInterface::TextureStorageInterface() + : mTextureSerial(issueTextureSerial()), + mInstance(NULL) +{ +} + +TextureStorageInterface::~TextureStorageInterface() +{ + delete mInstance; +} + +bool TextureStorageInterface::isRenderTarget() const +{ + return mInstance->isRenderTarget(); +} + +bool TextureStorageInterface::isManaged() const +{ + return mInstance->isManaged(); +} + +unsigned int TextureStorageInterface::getTextureSerial() const +{ + return mTextureSerial; +} + +unsigned int TextureStorageInterface::issueTextureSerial() +{ + return mCurrentTextureSerial++; +} + +int TextureStorageInterface::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 new file mode 100644 index 0000000000..0a212e16f2 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h @@ -0,0 +1,145 @@ +// +// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureStorage.h: Defines the abstract rx::TextureStorageInterface class and its concrete derived +// classes TextureStorageInterface2D and TextureStorageInterfaceCube, which act as the interface to the +// GPU-side texture. + +#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ +#define LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ + +#include "common/debug.h" + +namespace rx +{ +class Renderer; +class SwapChain; +class RenderTarget; + +class TextureStorage +{ + public: + TextureStorage() {}; + virtual ~TextureStorage() {}; + + virtual int getTopLevel() const = 0; + virtual bool isRenderTarget() const = 0; + virtual bool isManaged() const = 0; + virtual int getLevelCount() const = 0; + + virtual 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; } + + unsigned int getTextureSerial() const; + + virtual int getTopLevel() const; + virtual bool isRenderTarget() const; + virtual bool isManaged() const; + virtual int getLevelCount() const; + + protected: + TextureStorage *mInstance; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorageInterface); + + const unsigned int mTextureSerial; + static unsigned int issueTextureSerial(); + + static unsigned int mCurrentTextureSerial; +}; + +class TextureStorageInterface2D : public TextureStorageInterface +{ + public: + TextureStorageInterface2D(Renderer *renderer, SwapChain *swapchain); + TextureStorageInterface2D(Renderer *renderer, 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; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp new file mode 100644 index 0000000000..901ca196a8 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp @@ -0,0 +1,296 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface +// class with derivations, classes that perform graphics API agnostic vertex buffer operations. + +#include "libGLESv2/renderer/d3d/VertexBuffer.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/renderer/d3d/BufferD3D.h" +#include "common/mathutil.h" + +namespace rx +{ + +unsigned int VertexBuffer::mNextSerial = 1; + +VertexBuffer::VertexBuffer() +{ + updateSerial(); +} + +VertexBuffer::~VertexBuffer() +{ +} + +void VertexBuffer::updateSerial() +{ + mSerial = mNextSerial++; +} + +unsigned int VertexBuffer::getSerial() const +{ + return mSerial; +} + +VertexBufferInterface::VertexBufferInterface(rx::Renderer *renderer, bool dynamic) : mRenderer(renderer) +{ + mDynamic = dynamic; + mWritePosition = 0; + mReservedSpace = 0; + + mVertexBuffer = renderer->createVertexBuffer(); +} + +VertexBufferInterface::~VertexBufferInterface() +{ + delete mVertexBuffer; +} + +unsigned int VertexBufferInterface::getSerial() const +{ + return mVertexBuffer->getSerial(); +} + +unsigned int VertexBufferInterface::getBufferSize() const +{ + return mVertexBuffer->getBufferSize(); +} + +bool VertexBufferInterface::setBufferSize(unsigned int size) +{ + if (mVertexBuffer->getBufferSize() == 0) + { + return mVertexBuffer->initialize(size, mDynamic); + } + else + { + return mVertexBuffer->setBufferSize(size); + } +} + +unsigned int VertexBufferInterface::getWritePosition() const +{ + return mWritePosition; +} + +void VertexBufferInterface::setWritePosition(unsigned int writePosition) +{ + mWritePosition = writePosition; +} + +bool VertexBufferInterface::discard() +{ + return mVertexBuffer->discard(); +} + +bool VertexBufferInterface::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int *outStreamOffset) +{ + unsigned int spaceRequired; + if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &spaceRequired)) + { + return false; + } + + if (mWritePosition + spaceRequired < mWritePosition) + { + return false; + } + + if (!reserveSpace(mReservedSpace)) + { + return false; + } + mReservedSpace = 0; + + if (!mVertexBuffer->storeVertexAttributes(attrib, currentValue, start, count, instances, mWritePosition)) + { + return false; + } + + if (outStreamOffset) + { + *outStreamOffset = mWritePosition; + } + + mWritePosition += spaceRequired; + + // Align to 16-byte boundary + mWritePosition = rx::roundUp(mWritePosition, 16u); + + return true; +} + +bool VertexBufferInterface::reserveVertexSpace(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances) +{ + unsigned int requiredSpace; + if (!mVertexBuffer->getSpaceRequired(attrib, count, instances, &requiredSpace)) + { + return false; + } + + // Protect against integer overflow + if (mReservedSpace + requiredSpace < mReservedSpace) + { + return false; + } + + mReservedSpace += requiredSpace; + + // Align to 16-byte boundary + mReservedSpace = rx::roundUp(mReservedSpace, 16u); + + return true; +} + +VertexBuffer* VertexBufferInterface::getVertexBuffer() const +{ + return mVertexBuffer; +} + +bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue) const +{ + gl::Buffer *buffer = attrib.buffer.get(); + BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL; + + if (!storage || !storage->supportsDirectBinding()) + { + return false; + } + + // Alignment restrictions: In D3D, vertex data must be aligned to + // the format stride, or to a 4-byte boundary, whichever is smaller. + // (Undocumented, and experimentally confirmed) + size_t alignment = 4; + bool requiresConversion = false; + + if (attrib.type != GL_FLOAT) + { + gl::VertexFormat vertexFormat(attrib, currentValue.Type); + + unsigned int outputElementSize; + getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize); + alignment = std::min(outputElementSize, 4); + + requiresConversion = (mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) != 0; + } + + bool isAligned = (static_cast(ComputeVertexAttributeStride(attrib)) % alignment == 0) && + (static_cast(attrib.offset) % alignment == 0); + + return !requiresConversion && isAligned; +} + +StreamingVertexBufferInterface::StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true) +{ + setBufferSize(initialSize); +} + +StreamingVertexBufferInterface::~StreamingVertexBufferInterface() +{ +} + +bool StreamingVertexBufferInterface::reserveSpace(unsigned int size) +{ + bool result = true; + unsigned int curBufferSize = getBufferSize(); + if (size > curBufferSize) + { + result = setBufferSize(std::max(size, 3 * curBufferSize / 2)); + setWritePosition(0); + } + else if (getWritePosition() + size > curBufferSize) + { + if (!discard()) + { + return false; + } + setWritePosition(0); + } + + return result; +} + +StaticVertexBufferInterface::StaticVertexBufferInterface(rx::Renderer *renderer) : VertexBufferInterface(renderer, false) +{ +} + +StaticVertexBufferInterface::~StaticVertexBufferInterface() +{ +} + +bool StaticVertexBufferInterface::lookupAttribute(const gl::VertexAttribute &attrib, unsigned int *outStreamOffset) +{ + for (unsigned int element = 0; element < mCache.size(); element++) + { + if (mCache[element].type == attrib.type && + mCache[element].size == attrib.size && + mCache[element].stride == ComputeVertexAttributeStride(attrib) && + mCache[element].normalized == attrib.normalized && + mCache[element].pureInteger == attrib.pureInteger) + { + size_t offset = (static_cast(attrib.offset) % ComputeVertexAttributeStride(attrib)); + if (mCache[element].attributeOffset == offset) + { + if (outStreamOffset) + { + *outStreamOffset = mCache[element].streamOffset; + } + return true; + } + } + } + + return false; +} + +bool StaticVertexBufferInterface::reserveSpace(unsigned int size) +{ + unsigned int curSize = getBufferSize(); + if (curSize == 0) + { + setBufferSize(size); + return true; + } + else if (curSize >= size) + { + return true; + } + else + { + UNREACHABLE(); // Static vertex buffers can't be resized + return false; + } +} + +bool 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)) + { + size_t attributeOffset = static_cast(attrib.offset) % ComputeVertexAttributeStride(attrib); + VertexElement element = { attrib.type, attrib.size, ComputeVertexAttributeStride(attrib), attrib.normalized, attrib.pureInteger, attributeOffset, streamOffset }; + mCache.push_back(element); + + if (outStreamOffset) + { + *outStreamOffset = streamOffset; + } + + return true; + } + else + { + return false; + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h new file mode 100644 index 0000000000..c5022d8c9c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h @@ -0,0 +1,138 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexBuffer.h: Defines the abstract VertexBuffer class and VertexBufferInterface +// class with derivations, classes that perform graphics API agnostic vertex buffer operations. + +#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER_H_ +#define LIBGLESV2_RENDERER_VERTEXBUFFER_H_ + +#include "common/angleutils.h" + +namespace gl +{ +struct VertexAttribute; +struct VertexAttribCurrentValueData; +} + +namespace rx +{ +class Renderer; + +class VertexBuffer +{ + public: + VertexBuffer(); + virtual ~VertexBuffer(); + + virtual bool initialize(unsigned int size, bool dynamicUsage) = 0; + + virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, 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 unsigned int getBufferSize() const = 0; + virtual bool setBufferSize(unsigned int size) = 0; + virtual bool discard() = 0; + + unsigned int getSerial() const; + + protected: + void updateSerial(); + + private: + DISALLOW_COPY_AND_ASSIGN(VertexBuffer); + + unsigned int mSerial; + static unsigned int mNextSerial; +}; + +class VertexBufferInterface +{ + public: + VertexBufferInterface(rx::Renderer *renderer, bool dynamic); + virtual ~VertexBufferInterface(); + + bool 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); + + bool directStoragePossible(const gl::VertexAttribute &attrib, + const gl::VertexAttribCurrentValueData ¤tValue) const; + + VertexBuffer* getVertexBuffer() const; + + protected: + virtual bool reserveSpace(unsigned int size) = 0; + + unsigned int getWritePosition() const; + void setWritePosition(unsigned int writePosition); + + bool discard(); + + bool setBufferSize(unsigned int size); + + private: + DISALLOW_COPY_AND_ASSIGN(VertexBufferInterface); + + rx::Renderer *const mRenderer; + + VertexBuffer* mVertexBuffer; + + unsigned int mWritePosition; + unsigned int mReservedSpace; + bool mDynamic; +}; + +class StreamingVertexBufferInterface : public VertexBufferInterface +{ + public: + StreamingVertexBufferInterface(rx::Renderer *renderer, std::size_t initialSize); + ~StreamingVertexBufferInterface(); + + protected: + bool reserveSpace(unsigned int size); +}; + +class StaticVertexBufferInterface : public VertexBufferInterface +{ + public: + explicit StaticVertexBufferInterface(rx::Renderer *renderer); + ~StaticVertexBufferInterface(); + + bool 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); + + private: + struct VertexElement + { + GLenum type; + GLuint size; + GLuint stride; + bool normalized; + bool pureInteger; + size_t attributeOffset; + + unsigned int streamOffset; + }; + + std::vector mCache; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXBUFFER_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp new file mode 100644 index 0000000000..fc2b8ff0df --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp @@ -0,0 +1,299 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexDataManager.h: Defines the VertexDataManager, a class that +// runs the Buffer translation process. + +#include "libGLESv2/renderer/d3d/VertexDataManager.h" +#include "libGLESv2/renderer/d3d/BufferD3D.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 +{ + enum { INITIAL_STREAM_BUFFER_SIZE = 1024*1024 }; + // This has to be at least 4k or else it fails on ATI cards. + enum { CONSTANT_VERTEX_BUFFER_SIZE = 4096 }; +} + +namespace rx +{ + +static int ElementsInBuffer(const gl::VertexAttribute &attrib, unsigned int size) +{ + // Size cannot be larger than a GLsizei + if (size > static_cast(std::numeric_limits::max())) + { + size = static_cast(std::numeric_limits::max()); + } + + GLsizei stride = ComputeVertexAttributeStride(attrib); + return (size - attrib.offset % stride + (stride - ComputeVertexAttributeTypeSize(attrib))) / stride; +} + +static int StreamingBufferElementCount(const gl::VertexAttribute &attrib, int vertexDrawCount, int instanceDrawCount) +{ + // For instanced rendering, we draw "instanceDrawCount" sets of "vertexDrawCount" vertices. + // + // A vertex attribute with a positive divisor loads one instanced vertex for every set of + // non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances. + if (instanceDrawCount > 0 && attrib.divisor > 0) + { + return instanceDrawCount / attrib.divisor; + } + + return vertexDrawCount; +} + +VertexDataManager::VertexDataManager(Renderer *renderer) : mRenderer(renderer) +{ + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mCurrentValue[i].FloatValues[0] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i].FloatValues[1] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i].FloatValues[2] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i].FloatValues[3] = std::numeric_limits::quiet_NaN(); + mCurrentValue[i].Type = GL_FLOAT; + mCurrentValueBuffer[i] = NULL; + mCurrentValueOffsets[i] = 0; + } + + mStreamingBuffer = new StreamingVertexBufferInterface(renderer, INITIAL_STREAM_BUFFER_SIZE); + + if (!mStreamingBuffer) + { + ERR("Failed to allocate the streaming vertex buffer."); + } +} + +VertexDataManager::~VertexDataManager() +{ + delete mStreamingBuffer; + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + delete mCurrentValueBuffer[i]; + } +} + +GLenum 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; + } + + 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) + { + 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(); + } + } + } + } + + // Reserve the required space in the buffers + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + 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])) + { + 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; + } + } + } + } + } + + // Perform the vertex data translations + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active) + { + if (attribs[i].enabled) + { + gl::Buffer *buffer = attribs[i].buffer.get(); + + if (!buffer && attribs[i].pointer == NULL) + { + // This is an application error that would normally result in a crash, but we catch it and return an error + ERR("An enabled vertex array has no buffer and no pointer."); + return GL_INVALID_OPERATION; + } + + 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 + { + if (!mCurrentValueBuffer[i]) + { + mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE); + } + + StreamingVertexBufferInterface *buffer = mCurrentValueBuffer[i]; + + if (mCurrentValue[i] != currentValues[i]) + { + 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; + } + + 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]; + } + } + } + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (translated[i].active && attribs[i].enabled) + { + gl::Buffer *buffer = attribs[i].buffer.get(); + + if (buffer) + { + BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation()); + bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(attribs[i])); + } + } + } + + return 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 new file mode 100644 index 0000000000..4164fbecbb --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h @@ -0,0 +1,70 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexDataManager.h: Defines the VertexDataManager, a class that +// runs the Buffer translation process. + +#ifndef LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ +#define LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ + +#include "libGLESv2/Constants.h" +#include "libGLESv2/VertexAttribute.h" +#include "common/angleutils.h" + +namespace gl +{ +struct VertexAttribute; +class ProgramBinary; +struct VertexAttribCurrentValueData; +} + +namespace rx +{ +class BufferD3D; +class StreamingVertexBufferInterface; +class VertexBuffer; +class Renderer; + +struct TranslatedAttribute +{ + bool active; + + const gl::VertexAttribute *attribute; + GLenum currentValueType; + unsigned int offset; + unsigned int stride; // 0 means not to advance the read pointer at all + + VertexBuffer *vertexBuffer; + BufferD3D *storage; + unsigned int serial; + unsigned int divisor; +}; + +class VertexDataManager +{ + public: + VertexDataManager(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); + + private: + DISALLOW_COPY_AND_ASSIGN(VertexDataManager); + + rx::Renderer *const mRenderer; + + StreamingVertexBufferInterface *mStreamingBuffer; + + gl::VertexAttribCurrentValueData mCurrentValue[gl::MAX_VERTEX_ATTRIBS]; + + StreamingVertexBufferInterface *mCurrentValueBuffer[gl::MAX_VERTEX_ATTRIBS]; + std::size_t mCurrentValueOffsets[gl::MAX_VERTEX_ATTRIBS]; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp new file mode 100644 index 0000000000..9b0f336ac7 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp @@ -0,0 +1,1049 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// 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/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2duips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2duips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2duips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2duips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2dps.h" + +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3dvs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3dgs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3duips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3duips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3duips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3duips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3dps.h" + +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h" + +namespace rx +{ + +static DXGI_FORMAT GetTextureFormat(ID3D11Resource *resource) +{ + ID3D11Texture2D *texture = d3d11::DynamicCastComObject(resource); + if (!texture) + { + return DXGI_FORMAT_UNKNOWN; + } + + D3D11_TEXTURE2D_DESC desc; + texture->GetDesc(&desc); + + SafeRelease(texture); + + return desc.Format; +} + +static ID3D11Resource *CreateStagingTexture(ID3D11Device *device, ID3D11DeviceContext *context, + ID3D11Resource *source, unsigned int subresource, + const gl::Extents &size, unsigned int cpuAccessFlags) +{ + D3D11_TEXTURE2D_DESC stagingDesc; + stagingDesc.Width = size.width; + stagingDesc.Height = size.height; + stagingDesc.MipLevels = 1; + stagingDesc.ArraySize = 1; + stagingDesc.Format = GetTextureFormat(source); + stagingDesc.SampleDesc.Count = 1; + stagingDesc.SampleDesc.Quality = 0; + stagingDesc.Usage = D3D11_USAGE_STAGING; + stagingDesc.CPUAccessFlags = cpuAccessFlags; + stagingDesc.MiscFlags = 0; + stagingDesc.BindFlags = 0; + + ID3D11Texture2D *stagingTexture = NULL; + HRESULT result = device->CreateTexture2D(&stagingDesc, NULL, &stagingTexture); + if (FAILED(result)) + { + ERR("Failed to create staging texture for depth stencil blit. HRESULT: 0x%X.", result); + return NULL; + } + + context->CopySubresourceRegion(stagingTexture, 0, 0, 0, 0, source, subresource, NULL); + + return stagingTexture; +} + +inline static void GenerateVertexCoords(const gl::Box &sourceArea, const gl::Extents &sourceSize, + const gl::Box &destArea, const gl::Extents &destSize, + float *x1, float *y1, float *x2, float *y2, + float *u1, float *v1, float *u2, float *v2) +{ + *x1 = (destArea.x / float(destSize.width)) * 2.0f - 1.0f; + *y1 = ((destSize.height - destArea.y - destArea.height) / float(destSize.height)) * 2.0f - 1.0f; + *x2 = ((destArea.x + destArea.width) / float(destSize.width)) * 2.0f - 1.0f; + *y2 = ((destSize.height - destArea.y) / float(destSize.height)) * 2.0f - 1.0f; + + *u1 = sourceArea.x / float(sourceSize.width); + *v1 = sourceArea.y / float(sourceSize.height); + *u2 = (sourceArea.x + sourceArea.width) / float(sourceSize.width); + *v2 = (sourceArea.y + sourceArea.height) / float(sourceSize.height); +} + +static void Write2DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize, + const gl::Box &destArea, const gl::Extents &destSize, + void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, + D3D11_PRIMITIVE_TOPOLOGY *outTopology) +{ + float x1, y1, x2, y2, u1, v1, u2, v2; + GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, &u2, &v2); + + d3d11::PositionTexCoordVertex *vertices = static_cast(outVertices); + + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2); + d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1); + d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2); + d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1); + + *outStride = sizeof(d3d11::PositionTexCoordVertex); + *outVertexCount = 4; + *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; +} + +static void Write3DVertices(const gl::Box &sourceArea, const gl::Extents &sourceSize, + const gl::Box &destArea, const gl::Extents &destSize, + void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, + D3D11_PRIMITIVE_TOPOLOGY *outTopology) +{ + ASSERT(sourceSize.depth > 0 && destSize.depth > 0); + + float x1, y1, x2, y2, u1, v1, u2, v2; + GenerateVertexCoords(sourceArea, sourceSize, destArea, destSize, &x1, &y1, &x2, &y2, &u1, &v1, &u2, &v2); + + d3d11::PositionLayerTexCoord3DVertex *vertices = static_cast(outVertices); + + for (int i = 0; i < destSize.depth; i++) + { + float readDepth = (float)i / std::max(destSize.depth - 1, 1); + + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 0], x1, y1, i, u1, v2, readDepth); + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 1], x1, y2, i, u1, v1, readDepth); + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 2], x2, y1, i, u2, v2, readDepth); + + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 3], x1, y2, i, u1, v1, readDepth); + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 4], x2, y2, i, u2, v1, readDepth); + d3d11::SetPositionLayerTexCoord3DVertex(&vertices[i * 6 + 5], x2, y1, i, u2, v2, readDepth); + } + + *outStride = sizeof(d3d11::PositionLayerTexCoord3DVertex); + *outVertexCount = destSize.depth * 6; + *outTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; +} + +Blit11::Blit11(rx::Renderer11 *renderer) + : mRenderer(renderer), mBlitShaderMap(compareBlitParameters), mSwizzleShaderMap(compareSwizzleParameters), + mVertexBuffer(NULL), mPointSampler(NULL), mLinearSampler(NULL), mScissorEnabledRasterizerState(NULL), + mScissorDisabledRasterizerState(NULL), mDepthStencilState(NULL), + mQuad2DIL(NULL), mQuad2DVS(NULL), mDepthPS(NULL), + mQuad3DIL(NULL), mQuad3DVS(NULL), mQuad3DGS(NULL), + mSwizzleCB(NULL) +{ + HRESULT result; + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_BUFFER_DESC vbDesc; + vbDesc.ByteWidth = std::max(sizeof(d3d11::PositionLayerTexCoord3DVertex), sizeof(d3d11::PositionTexCoordVertex)) * + 6 * renderer->getRendererCaps().max3DTextureSize; + vbDesc.Usage = D3D11_USAGE_DYNAMIC; + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vbDesc.MiscFlags = 0; + vbDesc.StructureByteStride = 0; + + result = device->CreateBuffer(&vbDesc, NULL, &mVertexBuffer); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mVertexBuffer, "Blit11 vertex buffer"); + + D3D11_SAMPLER_DESC pointSamplerDesc; + pointSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR; + pointSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + pointSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + pointSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + pointSamplerDesc.MipLODBias = 0.0f; + pointSamplerDesc.MaxAnisotropy = 0; + pointSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + pointSamplerDesc.BorderColor[0] = 0.0f; + pointSamplerDesc.BorderColor[1] = 0.0f; + pointSamplerDesc.BorderColor[2] = 0.0f; + pointSamplerDesc.BorderColor[3] = 0.0f; + pointSamplerDesc.MinLOD = 0.0f; + pointSamplerDesc.MaxLOD = mRenderer->isLevel9() ? FLT_MAX : 0.0f; + + result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPointSampler, "Blit11 point sampler"); + + D3D11_SAMPLER_DESC linearSamplerDesc; + linearSamplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + linearSamplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + linearSamplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + linearSamplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + linearSamplerDesc.MipLODBias = 0.0f; + linearSamplerDesc.MaxAnisotropy = 0; + linearSamplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + linearSamplerDesc.BorderColor[0] = 0.0f; + linearSamplerDesc.BorderColor[1] = 0.0f; + linearSamplerDesc.BorderColor[2] = 0.0f; + linearSamplerDesc.BorderColor[3] = 0.0f; + linearSamplerDesc.MinLOD = 0.0f; + linearSamplerDesc.MaxLOD = mRenderer->isLevel9() ? FLT_MAX : 0.0f; + + result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mLinearSampler, "Blit11 linear sampler"); + + // Use a rasterizer state that will not cull so that inverted quads will not be culled + D3D11_RASTERIZER_DESC rasterDesc; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.CullMode = D3D11_CULL_NONE; + rasterDesc.FrontCounterClockwise = FALSE; + rasterDesc.DepthBias = 0; + rasterDesc.SlopeScaledDepthBias = 0.0f; + rasterDesc.DepthBiasClamp = 0.0f; + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.MultisampleEnable = FALSE; + rasterDesc.AntialiasedLineEnable = FALSE; + + rasterDesc.ScissorEnable = TRUE; + result = device->CreateRasterizerState(&rasterDesc, &mScissorEnabledRasterizerState); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mScissorEnabledRasterizerState, "Blit11 scissoring rasterizer state"); + + rasterDesc.ScissorEnable = FALSE; + result = device->CreateRasterizerState(&rasterDesc, &mScissorDisabledRasterizerState); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mScissorDisabledRasterizerState, "Blit11 no scissoring rasterizer state"); + + D3D11_DEPTH_STENCIL_DESC depthStencilDesc; + depthStencilDesc.DepthEnable = true; + depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.StencilEnable = FALSE; + depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; + depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; + depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + result = device->CreateDepthStencilState(&depthStencilDesc, &mDepthStencilState); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthStencilState, "Blit11 depth stencil state"); + + D3D11_INPUT_ELEMENT_DESC quad2DLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + result = device->CreateInputLayout(quad2DLayout, ArraySize(quad2DLayout), g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), &mQuad2DIL); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuad2DIL, "Blit11 2D input layout"); + + result = device->CreateVertexShader(g_VS_Passthrough2D, ArraySize(g_VS_Passthrough2D), NULL, &mQuad2DVS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuad2DVS, "Blit11 2D vertex shader"); + + if (!renderer->isLevel9()) + { + result = device->CreatePixelShader(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), NULL, &mDepthPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthPS, "Blit11 2D depth pixel shader"); + + D3D11_INPUT_ELEMENT_DESC quad3DLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + result = device->CreateInputLayout(quad3DLayout, ArraySize(quad3DLayout), g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), &mQuad3DIL); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuad3DIL, "Blit11 3D input layout"); + + result = device->CreateVertexShader(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), NULL, &mQuad3DVS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuad3DVS, "Blit11 3D vertex shader"); + + result = device->CreateGeometryShader(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), NULL, &mQuad3DGS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuad3DGS, "Renderer11 copy 3D texture geometry shader"); + + } + + buildShaderMap(); + + D3D11_BUFFER_DESC swizzleBufferDesc; + swizzleBufferDesc.ByteWidth = sizeof(unsigned int) * 4; + swizzleBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + swizzleBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + swizzleBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + swizzleBufferDesc.MiscFlags = 0; + swizzleBufferDesc.StructureByteStride = 0; + + result = device->CreateBuffer(&swizzleBufferDesc, NULL, &mSwizzleCB); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mSwizzleCB, "Blit11 swizzle constant buffer"); +} + +Blit11::~Blit11() +{ + SafeRelease(mVertexBuffer); + SafeRelease(mPointSampler); + SafeRelease(mLinearSampler); + SafeRelease(mScissorEnabledRasterizerState); + SafeRelease(mScissorDisabledRasterizerState); + SafeRelease(mDepthStencilState); + + SafeRelease(mQuad2DIL); + SafeRelease(mQuad2DVS); + SafeRelease(mDepthPS); + + SafeRelease(mQuad3DIL); + SafeRelease(mQuad3DVS); + SafeRelease(mQuad3DGS); + + SafeRelease(mSwizzleCB); + + clearShaderMap(); +} + +static inline unsigned int GetSwizzleIndex(GLenum swizzle) +{ + unsigned int colorIndex = 0; + + switch (swizzle) + { + case GL_RED: colorIndex = 0; break; + case GL_GREEN: colorIndex = 1; break; + case GL_BLUE: colorIndex = 2; break; + case GL_ALPHA: colorIndex = 3; break; + case GL_ZERO: colorIndex = 4; break; + case GL_ONE: colorIndex = 5; break; + default: UNREACHABLE(); break; + } + + return colorIndex; +} + +bool 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); + + GLenum shaderType = GL_NONE; + switch (gl::GetComponentType(sourceInternalFormat)) + { + case GL_UNSIGNED_NORMALIZED: + case GL_SIGNED_NORMALIZED: + case GL_FLOAT: + shaderType = GL_FLOAT; + break; + case GL_INT: + shaderType = GL_INT; + break; + case GL_UNSIGNED_INT: + shaderType = GL_UNSIGNED_INT; + break; + default: + UNREACHABLE(); + break; + } + + SwizzleParameters parameters = { 0 }; + parameters.mDestinationType = shaderType; + parameters.mViewDimension = sourceSRVDesc.ViewDimension; + + SwizzleShaderMap::const_iterator i = mSwizzleShaderMap.find(parameters); + if (i == mSwizzleShaderMap.end()) + { + UNREACHABLE(); + return false; + } + + const Shader &shader = i->second; + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Failed to map vertex buffer for texture swizzle, HRESULT: 0x%X.", result); + return false; + } + + UINT stride = 0; + UINT startIdx = 0; + UINT drawCount = 0; + D3D11_PRIMITIVE_TOPOLOGY topology; + + gl::Box area(0, 0, 0, size.width, size.height, size.depth); + shader.mVertexWriteFunction(area, size, area, size, mappedResource.pData, &stride, &drawCount, &topology); + + deviceContext->Unmap(mVertexBuffer, 0); + + // Set constant buffer + result = deviceContext->Map(mSwizzleCB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Failed to map constant buffer for texture swizzle, HRESULT: 0x%X.", result); + return false; + } + + unsigned int *swizzleIndices = reinterpret_cast(mappedResource.pData); + swizzleIndices[0] = GetSwizzleIndex(swizzleRed); + swizzleIndices[1] = GetSwizzleIndex(swizzleGreen); + swizzleIndices[2] = GetSwizzleIndex(swizzleBlue); + swizzleIndices[3] = GetSwizzleIndex(swizzleAlpha); + + deviceContext->Unmap(mSwizzleCB, 0); + + // Apply vertex buffer + deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + + // Apply constant buffer + deviceContext->PSSetConstantBuffers(0, 1, &mSwizzleCB); + + // Apply state + deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); + deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); + deviceContext->RSSetState(mScissorDisabledRasterizerState); + + // Apply shaders + deviceContext->IASetInputLayout(shader.mInputLayout); + deviceContext->IASetPrimitiveTopology(topology); + deviceContext->VSSetShader(shader.mVertexShader, NULL, 0); + + deviceContext->PSSetShader(shader.mPixelShader, NULL, 0); + deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0); + + // Unset the currently bound shader resource to avoid conflicts + ID3D11ShaderResourceView *const nullSRV = NULL; + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + + // Apply render target + mRenderer->setOneTimeRenderTarget(dest); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = size.width; + viewport.Height = size.height; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + deviceContext->PSSetShaderResources(0, 1, &source); + + // Apply samplers + deviceContext->PSSetSamplers(0, 1, &mPointSampler); + + // Draw the quad + deviceContext->Draw(drawCount, 0); + + // Unbind textures and render targets and vertex buffer + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + + mRenderer->unapplyRenderTargets(); + + UINT zero = 0; + ID3D11Buffer *const nullBuffer = NULL; + deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + + mRenderer->markAllStateDirty(); + + return true; +} + +bool Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11RenderTargetView *dest, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor, GLenum destFormat, GLenum filter) +{ + HRESULT result; + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + // Determine if the source format is a signed integer format, the destFormat will already + // be GL_XXXX_INTEGER but it does not tell us if it is signed or unsigned. + D3D11_SHADER_RESOURCE_VIEW_DESC sourceSRVDesc; + source->GetDesc(&sourceSRVDesc); + GLenum sourceInternalFormat = d3d11_gl::GetInternalFormat(sourceSRVDesc.Format); + + BlitParameters parameters = { 0 }; + parameters.mDestinationFormat = destFormat; + parameters.mSignedInteger = gl::GetComponentType(sourceInternalFormat) == GL_INT; + parameters.m3DBlit = sourceArea.depth > 1; + + BlitShaderMap::const_iterator i = mBlitShaderMap.find(parameters); + if (i == mBlitShaderMap.end()) + { + UNREACHABLE(); + return false; + } + + const Shader& shader = i->second; + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result); + return false; + } + + UINT stride = 0; + UINT startIdx = 0; + UINT drawCount = 0; + D3D11_PRIMITIVE_TOPOLOGY topology; + + shader.mVertexWriteFunction(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, + &stride, &drawCount, &topology); + + deviceContext->Unmap(mVertexBuffer, 0); + + // Apply vertex buffer + deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + + // Apply state + deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); + deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); + + if (scissor) + { + D3D11_RECT scissorRect; + scissorRect.left = scissor->x; + scissorRect.right = scissor->x + scissor->width; + scissorRect.top = scissor->y; + scissorRect.bottom = scissor->y + scissor->height; + + deviceContext->RSSetScissorRects(1, &scissorRect); + deviceContext->RSSetState(mScissorEnabledRasterizerState); + } + else + { + deviceContext->RSSetState(mScissorDisabledRasterizerState); + } + + // Apply shaders + deviceContext->IASetInputLayout(shader.mInputLayout); + deviceContext->IASetPrimitiveTopology(topology); + deviceContext->VSSetShader(shader.mVertexShader, NULL, 0); + + deviceContext->PSSetShader(shader.mPixelShader, NULL, 0); + deviceContext->GSSetShader(shader.mGeometryShader, NULL, 0); + + // Unset the currently bound shader resource to avoid conflicts + ID3D11ShaderResourceView *const nullSRV = NULL; + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + + // Apply render target + mRenderer->setOneTimeRenderTarget(dest); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = destSize.width; + viewport.Height = destSize.height; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + deviceContext->PSSetShaderResources(0, 1, &source); + + // Apply samplers + ID3D11SamplerState *sampler = NULL; + switch (filter) + { + case GL_NEAREST: sampler = mPointSampler; break; + case GL_LINEAR: sampler = mLinearSampler; break; + default: UNREACHABLE(); return false; + } + deviceContext->PSSetSamplers(0, 1, &sampler); + + // Draw the quad + deviceContext->Draw(drawCount, 0); + + // Unbind textures and render targets and vertex buffer + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + + mRenderer->unapplyRenderTargets(); + + UINT zero = 0; + ID3D11Buffer *const nullBuffer = NULL; + deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + + mRenderer->markAllStateDirty(); + + return true; +} + +bool Blit11::copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor) +{ + return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize, + dest, destSubresource, destArea, destSize, + scissor, true); +} + +bool Blit11::copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor) +{ + HRESULT result; + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result); + return false; + } + + UINT stride = 0; + UINT startIdx = 0; + UINT drawCount = 0; + D3D11_PRIMITIVE_TOPOLOGY topology; + + Write2DVertices(sourceArea, sourceSize, destArea, destSize, mappedResource.pData, + &stride, &drawCount, &topology); + + deviceContext->Unmap(mVertexBuffer, 0); + + // Apply vertex buffer + deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &startIdx); + + // Apply state + deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); + deviceContext->OMSetDepthStencilState(mDepthStencilState, 0xFFFFFFFF); + + if (scissor) + { + D3D11_RECT scissorRect; + scissorRect.left = scissor->x; + scissorRect.right = scissor->x + scissor->width; + scissorRect.top = scissor->y; + scissorRect.bottom = scissor->y + scissor->height; + + deviceContext->RSSetScissorRects(1, &scissorRect); + deviceContext->RSSetState(mScissorEnabledRasterizerState); + } + else + { + deviceContext->RSSetState(mScissorDisabledRasterizerState); + } + + // Apply shaders + deviceContext->IASetInputLayout(mQuad2DIL); + deviceContext->IASetPrimitiveTopology(topology); + deviceContext->VSSetShader(mQuad2DVS, NULL, 0); + + deviceContext->PSSetShader(mDepthPS, NULL, 0); + deviceContext->GSSetShader(NULL, NULL, 0); + + // Unset the currently bound shader resource to avoid conflicts + ID3D11ShaderResourceView *const nullSRV = NULL; + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + + // Apply render target + deviceContext->OMSetRenderTargets(0, NULL, dest); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = destSize.width; + viewport.Height = destSize.height; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + deviceContext->PSSetShaderResources(0, 1, &source); + + // Apply samplers + deviceContext->PSSetSamplers(0, 1, &mPointSampler); + + // Draw the quad + deviceContext->Draw(drawCount, 0); + + // Unbind textures and render targets and vertex buffer + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + + mRenderer->unapplyRenderTargets(); + + UINT zero = 0; + ID3D11Buffer *const nullBuffer = NULL; + deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + + mRenderer->markAllStateDirty(); + + return true; +} + +bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor) +{ + return copyDepthStencil(source, sourceSubresource, sourceArea, sourceSize, + dest, destSubresource, destArea, destSize, + scissor, false); +} + +bool Blit11::copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor, bool stencilOnly) +{ + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + ID3D11Resource *sourceStaging = CreateStagingTexture(device, deviceContext, source, sourceSubresource, sourceSize, D3D11_CPU_ACCESS_READ); + // HACK: Create the destination staging buffer as a read/write texture so ID3D11DevicContext::UpdateSubresource can be called + // using it's mapped data as a source + ID3D11Resource *destStaging = CreateStagingTexture(device, deviceContext, dest, destSubresource, destSize, D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE); + + if (!sourceStaging || !destStaging) + { + SafeRelease(sourceStaging); + SafeRelease(destStaging); + return false; + } + + DXGI_FORMAT format = GetTextureFormat(source); + ASSERT(format == GetTextureFormat(dest)); + + unsigned int pixelSize = d3d11::GetFormatPixelBytes(format); + unsigned int copyOffset = 0; + unsigned int copySize = pixelSize; + if (stencilOnly) + { + copyOffset = d3d11::GetStencilOffset(format) / 8; + copySize = d3d11::GetStencilBits(format) / 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); + } + + D3D11_MAPPED_SUBRESOURCE sourceMapping, destMapping; + deviceContext->Map(sourceStaging, 0, D3D11_MAP_READ, 0, &sourceMapping); + deviceContext->Map(destStaging, 0, D3D11_MAP_WRITE, 0, &destMapping); + + if (!sourceMapping.pData || !destMapping.pData) + { + if (!sourceMapping.pData) + { + deviceContext->Unmap(sourceStaging, 0); + } + if (!destMapping.pData) + { + deviceContext->Unmap(destStaging, 0); + } + SafeRelease(sourceStaging); + SafeRelease(destStaging); + return false; + } + + gl::Rectangle clippedDestArea(destArea.x, destArea.y, destArea.width, destArea.height); + + // Clip dest area to the destination size + gl::ClipRectangle(clippedDestArea, gl::Rectangle(0, 0, destSize.width, destSize.height), &clippedDestArea); + + // Clip dest area to the scissor + if (scissor) + { + gl::ClipRectangle(clippedDestArea, *scissor, &clippedDestArea); + } + + // Determine if entire rows can be copied at once instead of each individual pixel, requires that there is + // no out of bounds lookups required, the entire pixel is copied and no stretching + bool wholeRowCopy = sourceArea.width == clippedDestArea.width && + sourceArea.x >= 0 && sourceArea.x + sourceArea.width <= sourceSize.width && + copySize == pixelSize; + + for (int y = clippedDestArea.y; y < clippedDestArea.y + clippedDestArea.height; y++) + { + float yPerc = static_cast(y - destArea.y) / (destArea.height - 1); + + // Interpolate using the original source rectangle to determine which row to sample from while clamping to the edges + unsigned int readRow = gl::clamp(sourceArea.y + floor(yPerc * (sourceArea.height - 1) + 0.5f), 0, sourceSize.height - 1); + unsigned int writeRow = y; + + if (wholeRowCopy) + { + void *sourceRow = reinterpret_cast(sourceMapping.pData) + + readRow * sourceMapping.RowPitch + + sourceArea.x * pixelSize; + + void *destRow = reinterpret_cast(destMapping.pData) + + writeRow * destMapping.RowPitch + + destArea.x * pixelSize; + + memcpy(destRow, sourceRow, pixelSize * destArea.width); + } + else + { + for (int x = clippedDestArea.x; x < clippedDestArea.x + clippedDestArea.width; x++) + { + float xPerc = static_cast(x - destArea.x) / (destArea.width - 1); + + // Interpolate the original source rectangle to determine which column to sample from while clamping to the edges + unsigned int readColumn = gl::clamp(sourceArea.x + floor(xPerc * (sourceArea.width - 1) + 0.5f), 0, sourceSize.width - 1); + unsigned int writeColumn = x; + + void *sourcePixel = reinterpret_cast(sourceMapping.pData) + + readRow * sourceMapping.RowPitch + + readColumn * pixelSize + + copyOffset; + + void *destPixel = reinterpret_cast(destMapping.pData) + + writeRow * destMapping.RowPitch + + writeColumn * pixelSize + + copyOffset; + + memcpy(destPixel, sourcePixel, copySize); + } + } + } + + // HACK: Use ID3D11DevicContext::UpdateSubresource which causes an extra copy compared to ID3D11DevicContext::CopySubresourceRegion + // according to MSDN. + deviceContext->UpdateSubresource(dest, destSubresource, NULL, destMapping.pData, destMapping.RowPitch, destMapping.DepthPitch); + + deviceContext->Unmap(sourceStaging, 0); + deviceContext->Unmap(destStaging, 0); + + // TODO: Determine why this call to ID3D11DevicContext::CopySubresourceRegion causes a TDR timeout on some + // systems when called repeatedly. + // deviceContext->CopySubresourceRegion(dest, destSubresource, 0, 0, 0, destStaging, 0, NULL); + + SafeRelease(sourceStaging); + SafeRelease(destStaging); + + return true; +} + +bool Blit11::compareBlitParameters(const Blit11::BlitParameters &a, const Blit11::BlitParameters &b) +{ + return memcmp(&a, &b, sizeof(Blit11::BlitParameters)) < 0; +} + +bool Blit11::compareSwizzleParameters(const SwizzleParameters &a, const SwizzleParameters &b) +{ + return memcmp(&a, &b, sizeof(Blit11::SwizzleParameters)) < 0; +} + +void Blit11::add2DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps) +{ + BlitParameters params = { 0 }; + params.mDestinationFormat = destFormat; + params.mSignedInteger = signedInteger; + params.m3DBlit = false; + + ASSERT(mBlitShaderMap.find(params) == mBlitShaderMap.end()); + ASSERT(ps); + + Shader shader; + shader.mVertexWriteFunction = Write2DVertices; + shader.mInputLayout = mQuad2DIL; + shader.mVertexShader = mQuad2DVS; + shader.mGeometryShader = NULL; + shader.mPixelShader = ps; + + mBlitShaderMap[params] = shader; +} + +void Blit11::add3DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps) +{ + BlitParameters params = { 0 }; + params.mDestinationFormat = destFormat; + params.mSignedInteger = signedInteger; + params.m3DBlit = true; + + ASSERT(mBlitShaderMap.find(params) == mBlitShaderMap.end()); + ASSERT(ps); + + Shader shader; + shader.mVertexWriteFunction = Write3DVertices; + shader.mInputLayout = mQuad3DIL; + shader.mVertexShader = mQuad3DVS; + shader.mGeometryShader = mQuad3DGS; + shader.mPixelShader = ps; + + mBlitShaderMap[params] = shader; +} + +void Blit11::addSwizzleShaderToMap(GLenum destType, D3D11_SRV_DIMENSION viewDimension, ID3D11PixelShader *ps) +{ + SwizzleParameters params = { 0 }; + params.mDestinationType = destType; + params.mViewDimension = viewDimension; + + ASSERT(mSwizzleShaderMap.find(params) == mSwizzleShaderMap.end()); + ASSERT(ps); + + Shader shader; + switch (viewDimension) + { + case D3D_SRV_DIMENSION_TEXTURE2D: + shader.mVertexWriteFunction = Write2DVertices; + shader.mInputLayout = mQuad2DIL; + shader.mVertexShader = mQuad2DVS; + shader.mGeometryShader = NULL; + break; + + case D3D_SRV_DIMENSION_TEXTURE3D: + case D3D_SRV_DIMENSION_TEXTURE2DARRAY: + case D3D_SRV_DIMENSION_TEXTURECUBE: + shader.mVertexWriteFunction = Write3DVertices; + shader.mInputLayout = mQuad3DIL; + shader.mVertexShader = mQuad3DVS; + shader.mGeometryShader = mQuad3DGS; + break; + + default: + UNREACHABLE(); + break; + } + shader.mPixelShader = ps; + + mSwizzleShaderMap[params] = shader; +} + +void Blit11::buildShaderMap() +{ + ID3D11Device *device = mRenderer->getDevice(); + + add2DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader" )); + add2DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA pixel shader" )); + add2DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2D, "Blit11 2D RGB pixel shader" )); + add2DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG2D, "Blit11 2D RG pixel shader" )); + add2DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR2D, "Blit11 2D R pixel shader" )); + add2DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D alpha pixel shader" )); + add2DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum2D, "Blit11 2D lum pixel shader" )); + add2DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D, "Blit11 2D luminance alpha pixel shader")); + + addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader" )); + + if (mRenderer->isLevel9()) + return; + + add2DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI, "Blit11 2D RGBA UI pixel shader" )); + add2DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader" )); + add2DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader" )); + add2DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader" )); + add2DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader" )); + add2DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader" )); + add2DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader" )); + add2DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader" )); + + add3DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader" )); + add3DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI, "Blit11 3D UI RGBA pixel shader" )); + add3DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader" )); + add3DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader" )); + add3DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader" )); + add3DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader" )); + add3DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader" )); + add3DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader" )); + add3DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader" )); + add3DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader" )); + add3DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader" )); + add3DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader" )); + add3DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader" )); + add3DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader" )); + add3DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum3D, "Blit11 3D luminance pixel shader" )); + add3DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader")); + + addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader")); + addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader" )); + + addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Cube F swizzle pixel shader" )); + addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Cube UI swizzle pixel shader")); + addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Cube I swizzle pixel shader" )); + + addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleF3D, "Blit11 3D F swizzle pixel shader" )); + addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleUI3D, "Blit11 3D UI swizzle pixel shader")); + addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleI3D, "Blit11 3D I swizzle pixel shader" )); + + addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Array F swizzle pixel shader" )); + addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Array UI swizzle pixel shader")); + addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Array I swizzle pixel shader" )); +} + +void Blit11::clearShaderMap() +{ + for (BlitShaderMap::iterator i = mBlitShaderMap.begin(); i != mBlitShaderMap.end(); ++i) + { + Shader &shader = i->second; + SafeRelease(shader.mPixelShader); + } + mBlitShaderMap.clear(); + + for (SwizzleShaderMap::iterator i = mSwizzleShaderMap.begin(); i != mSwizzleShaderMap.end(); ++i) + { + Shader &shader = i->second; + SafeRelease(shader.mPixelShader); + } + mSwizzleShaderMap.clear(); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h new file mode 100644 index 0000000000..fba89e20ba --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h @@ -0,0 +1,126 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Blit11.cpp: Texture copy utility class. + +#ifndef LIBGLESV2_BLIT11_H_ +#define LIBGLESV2_BLIT11_H_ + +#include "common/angleutils.h" +#include "libGLESv2/angletypes.h" + +namespace rx +{ +class Renderer11; + +enum Filter +{ + Point, + Linear, +}; + +class Blit11 +{ + public: + explicit Blit11(Renderer11 *renderer); + ~Blit11(); + + bool 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, + const gl::Rectangle *scissor, GLenum destFormat, GLenum filter); + + bool copyStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor); + + bool copyDepth(ID3D11ShaderResourceView *source, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11DepthStencilView *dest, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor); + + bool copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor); + + private: + rx::Renderer11 *mRenderer; + + struct BlitParameters + { + GLenum mDestinationFormat; + bool mSignedInteger; + bool m3DBlit; + }; + + bool copyDepthStencil(ID3D11Resource *source, unsigned int sourceSubresource, const gl::Box &sourceArea, const gl::Extents &sourceSize, + ID3D11Resource *dest, unsigned int destSubresource, const gl::Box &destArea, const gl::Extents &destSize, + const gl::Rectangle *scissor, bool stencilOnly); + + static bool compareBlitParameters(const BlitParameters &a, const BlitParameters &b); + + typedef void (*WriteVertexFunction)(const gl::Box &sourceArea, const gl::Extents &sourceSize, + const gl::Box &destArea, const gl::Extents &destSize, + void *outVertices, unsigned int *outStride, unsigned int *outVertexCount, + D3D11_PRIMITIVE_TOPOLOGY *outTopology); + + struct Shader + { + WriteVertexFunction mVertexWriteFunction; + ID3D11InputLayout *mInputLayout; + ID3D11VertexShader *mVertexShader; + ID3D11GeometryShader *mGeometryShader; + ID3D11PixelShader *mPixelShader; + }; + + typedef bool (*BlitParametersComparisonFunction)(const BlitParameters&, const BlitParameters &); + typedef std::map BlitShaderMap; + BlitShaderMap mBlitShaderMap; + + void add2DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps); + void add3DBlitShaderToMap(GLenum destFormat, bool signedInteger, ID3D11PixelShader *ps); + + struct SwizzleParameters + { + GLenum mDestinationType; + D3D11_SRV_DIMENSION mViewDimension; + }; + + static bool compareSwizzleParameters(const SwizzleParameters &a, const SwizzleParameters &b); + + typedef bool (*SwizzleParametersComparisonFunction)(const SwizzleParameters&, const SwizzleParameters &); + typedef std::map SwizzleShaderMap; + SwizzleShaderMap mSwizzleShaderMap; + + void addSwizzleShaderToMap(GLenum destType, D3D11_SRV_DIMENSION viewDimension, ID3D11PixelShader *ps); + + void buildShaderMap(); + void clearShaderMap(); + + ID3D11Buffer *mVertexBuffer; + ID3D11SamplerState *mPointSampler; + ID3D11SamplerState *mLinearSampler; + ID3D11RasterizerState *mScissorEnabledRasterizerState; + ID3D11RasterizerState *mScissorDisabledRasterizerState; + ID3D11DepthStencilState *mDepthStencilState; + + ID3D11InputLayout *mQuad2DIL; + ID3D11VertexShader *mQuad2DVS; + ID3D11PixelShader *mDepthPS; + + ID3D11InputLayout *mQuad3DIL; + ID3D11VertexShader *mQuad3DVS; + ID3D11GeometryShader *mQuad3DGS; + + ID3D11Buffer *mSwizzleCB; + + DISALLOW_COPY_AND_ASSIGN(Blit11); +}; + +} + +#endif // LIBGLESV2_BLIT11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp new file mode 100644 index 0000000000..352da9654a --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp @@ -0,0 +1,900 @@ +#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. +// + +// 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" + +namespace rx +{ + +PackPixelsParams::PackPixelsParams() + : format(GL_NONE), + type(GL_NONE), + outputPitch(0), + packBuffer(NULL), + offset(0) +{} + +PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn, GLenum formatIn, GLenum typeIn, GLuint outputPitchIn, + const gl::PixelPackState &packIn, ptrdiff_t offsetIn) + : area(areaIn), + format(formatIn), + type(typeIn), + outputPitch(outputPitchIn), + packBuffer(packIn.pixelBuffer.get()), + pack(packIn.alignment, packIn.reverseRowOrder), + offset(offsetIn) +{} + +namespace gl_d3d11 +{ + +D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access) +{ + bool readBit = ((access & GL_MAP_READ_BIT) != 0); + bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0); + + ASSERT(readBit || writeBit); + + // Note : we ignore the discard bit, because in D3D11, staging buffers + // don't accept the map-discard flag (discard only works for DYNAMIC usage) + + if (readBit && !writeBit) + { + return D3D11_MAP_READ; + } + else if (writeBit && !readBit) + { + return D3D11_MAP_WRITE; + } + else if (writeBit && readBit) + { + return D3D11_MAP_READ_WRITE; + } + else + { + UNREACHABLE(); + return D3D11_MAP_READ; + } +} + +} + +// Each instance of Buffer11::BufferStorage11 is specialized for a class of D3D binding points +// - vertex/transform feedback buffers +// - index buffers +// - pixel unpack buffers +// - uniform buffers +class Buffer11::BufferStorage11 +{ + public: + virtual ~BufferStorage11() {} + + DataRevision getDataRevision() const { return mRevision; } + BufferUsage getUsage() const { return mUsage; } + size_t getSize() const { return mBufferSize; } + bool isMappable() const { return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_PIXEL_PACK); } + + void setDataRevision(DataRevision rev) { mRevision = rev; } + + virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, + size_t size, size_t destOffset) = 0; + virtual bool resize(size_t size, bool preserveData) = 0; + + virtual void *map(size_t offset, size_t length, GLbitfield access) = 0; + virtual void unmap() = 0; + + protected: + BufferStorage11(Renderer11 *renderer, BufferUsage usage); + + Renderer11 *mRenderer; + DataRevision mRevision; + const BufferUsage mUsage; + size_t mBufferSize; +}; + +// A native buffer storage represents an underlying D3D11 buffer for a particular +// type of storage. +class Buffer11::NativeBuffer11 : public Buffer11::BufferStorage11 +{ + public: + NativeBuffer11(Renderer11 *renderer, BufferUsage usage); + ~NativeBuffer11(); + + ID3D11Buffer *getNativeBuffer() const { return mNativeBuffer; } + + virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, + size_t size, size_t destOffset); + virtual bool resize(size_t size, bool preserveData); + + virtual void *map(size_t offset, size_t length, GLbitfield access); + virtual void unmap(); + + private: + ID3D11Buffer *mNativeBuffer; + + static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize); +}; + +// Pack storage represents internal storage for pack buffers. We implement pack buffers +// as CPU memory, tied to a staging texture, for asynchronous texture readback. +class Buffer11::PackStorage11 : public Buffer11::BufferStorage11 +{ + public: + PackStorage11(Renderer11 *renderer); + ~PackStorage11(); + + virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset, + size_t size, size_t destOffset); + virtual bool resize(size_t size, bool preserveData); + + virtual void *map(size_t offset, size_t length, GLbitfield access); + virtual void unmap(); + + void packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms); + + private: + + void flushQueuedPackCommand(); + + ID3D11Texture2D *mStagingTexture; + DXGI_FORMAT mTextureFormat; + gl::Extents mTextureSize; + MemoryBuffer mMemoryBuffer; + PackPixelsParams *mQueuedPackCommand; + PackPixelsParams mPackParams; + bool mDataModified; +}; + + +Buffer11::Buffer11(Renderer11 *renderer) + : BufferD3D(), + mRenderer(renderer), + mSize(0), + mMappedStorage(NULL), + mResolvedDataRevision(0), + mReadUsageCount(0) +{ +} + +Buffer11::~Buffer11() +{ + clear(); +} + +Buffer11 *Buffer11::makeBuffer11(BufferImpl *buffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(Buffer11*, buffer)); + return static_cast(buffer); +} + +void Buffer11::clear() +{ + for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) + { + SafeDelete(it->second); + } + + 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(); + } +} + +void *Buffer11::getData() +{ + NativeBuffer11 *stagingBuffer = getStagingBuffer(); + + if (!stagingBuffer) + { + // Out-of-memory + return NULL; + } + + if (stagingBuffer->getDataRevision() > mResolvedDataRevision) + { + if (stagingBuffer->getSize() > mResolvedData.size()) + { + if (!mResolvedData.resize(stagingBuffer->getSize())) + { + return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); + } + } + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_READ, 0, &mappedResource); + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); + } + + memcpy(mResolvedData.data(), mappedResource.pData, stagingBuffer->getSize()); + + context->Unmap(stagingBuffer->getNativeBuffer(), 0); + + mResolvedDataRevision = stagingBuffer->getDataRevision(); + } + + mReadUsageCount = 0; + + return mResolvedData.data(); +} + +void 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) + { + NativeBuffer11 *stagingBuffer = getStagingBuffer(); + + if (!stagingBuffer) + { + // Out-of-memory + return; + } + + // Explicitly resize the staging buffer, preserving data if the new data will not + // completely fill the buffer + if (stagingBuffer->getSize() < requiredSize) + { + bool preserveData = (offset > 0); + if (!stagingBuffer->resize(requiredSize, preserveData)) + { + // Out-of-memory + return; + } + } + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_WRITE, 0, &mappedResource); + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY); + } + + unsigned char *offsetBufferPointer = reinterpret_cast(mappedResource.pData) + offset; + memcpy(offsetBufferPointer, data, size); + + context->Unmap(stagingBuffer->getNativeBuffer(), 0); + + stagingBuffer->setDataRevision(stagingBuffer->getDataRevision() + 1); + } +} + +void Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +{ + Buffer11 *sourceBuffer = makeBuffer11(source); + if (sourceBuffer) + { + BufferStorage11 *dest = getLatestBufferStorage(); + if (!dest) + { + dest = getStagingBuffer(); + } + + BufferStorage11 *source = sourceBuffer->getLatestBufferStorage(); + if (source && dest) + { + // 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); + } + + mSize = std::max(mSize, destOffset + size); + } + + invalidateStaticData(); +} + +GLvoid *Buffer11::map(size_t offset, size_t length, GLbitfield access) +{ + ASSERT(!mMappedStorage); + + BufferStorage11 *latestStorage = getLatestBufferStorage(); + if (latestStorage && + (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK || + latestStorage->getUsage() == BUFFER_USAGE_STAGING)) + { + // Latest storage is mappable. + mMappedStorage = latestStorage; + } + else + { + // Fall back to using the staging buffer if the latest storage does + // not exist or is not CPU-accessible. + mMappedStorage = getStagingBuffer(); + } + + if (!mMappedStorage) + { + // Out-of-memory + return NULL; + } + + if ((access & GL_MAP_WRITE_BIT) > 0) + { + // Update the data revision immediately, since the data might be changed at any time + mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1); + } + + return mMappedStorage->map(offset, length, access); +} + +void Buffer11::unmap() +{ + ASSERT(mMappedStorage); + mMappedStorage->unmap(); + mMappedStorage = NULL; +} + +void Buffer11::markTransformFeedbackUsage() +{ + BufferStorage11 *transformFeedbackStorage = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + + if (transformFeedbackStorage) + { + transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1); + } + + invalidateStaticData(); +} + +void Buffer11::markBufferUsage() +{ + mReadUsageCount++; + + const unsigned int usageLimit = 5; + + if (mReadUsageCount > usageLimit && mResolvedData.size() > 0) + { + mResolvedData.resize(0); + mResolvedDataRevision = 0; + } +} + +Renderer* Buffer11::getRenderer() +{ + return mRenderer; +} + +ID3D11Buffer *Buffer11::getBuffer(BufferUsage usage) +{ + markBufferUsage(); + + BufferStorage11 *bufferStorage = getBufferStorage(usage); + + if (!bufferStorage) + { + // Storage out-of-memory + return NULL; + } + + ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, bufferStorage)); + + return static_cast(bufferStorage)->getNativeBuffer(); +} + +ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat) +{ + BufferStorage11 *storage = getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK); + + if (!storage) + { + // Storage out-of-memory + return NULL; + } + + ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, storage)); + ID3D11Buffer *buffer = static_cast(storage)->getNativeBuffer(); + + auto bufferSRVIt = mBufferResourceViews.find(srvFormat); + + if (bufferSRVIt != mBufferResourceViews.end()) + { + if (bufferSRVIt->second.first == buffer) + { + return bufferSRVIt->second.second; + } + else + { + // The underlying buffer has changed since the SRV was created: recreate the SRV. + SafeRelease(bufferSRVIt->second.second); + } + } + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11ShaderResourceView *bufferSRV = NULL; + + D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc; + bufferSRVDesc.Buffer.ElementOffset = 0; + bufferSRVDesc.Buffer.ElementWidth = mSize / d3d11::GetFormatPixelBytes(srvFormat); + bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; + bufferSRVDesc.Format = srvFormat; + + HRESULT result = device->CreateShaderResourceView(buffer, &bufferSRVDesc, &bufferSRV); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + + mBufferResourceViews[srvFormat] = BufferSRVPair(buffer, bufferSRV); + + return bufferSRV; +} + +void Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams ¶ms) +{ + PackStorage11 *packStorage = getPackStorage(); + + BufferStorage11 *latestStorage = getLatestBufferStorage(); + + if (packStorage) + { + packStorage->packPixels(srcTexture, srcSubresource, params); + packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1); + } +} + +Buffer11::BufferStorage11 *Buffer11::getBufferStorage(BufferUsage usage) +{ + BufferStorage11 *directBuffer = NULL; + auto directBufferIt = mBufferStorages.find(usage); + if (directBufferIt != mBufferStorages.end()) + { + directBuffer = directBufferIt->second; + } + + if (!directBuffer) + { + if (usage == BUFFER_USAGE_PIXEL_PACK) + { + directBuffer = new PackStorage11(mRenderer); + } + else + { + // buffer is not allocated, create it + directBuffer = new NativeBuffer11(mRenderer, usage); + } + + mBufferStorages.insert(std::make_pair(usage, directBuffer)); + } + + // resize buffer + if (directBuffer->getSize() < mSize) + { + if (!directBuffer->resize(mSize, true)) + { + // Out of memory error + return NULL; + } + } + + BufferStorage11 *latestBuffer = getLatestBufferStorage(); + if (latestBuffer && latestBuffer->getDataRevision() > directBuffer->getDataRevision()) + { + // if copying from a pack buffer to a non-staging native buffer, we must first + // copy through the staging buffer, because other native buffers can't be mapped + if (latestBuffer->getUsage() == BUFFER_USAGE_PIXEL_PACK && !directBuffer->isMappable()) + { + NativeBuffer11 *stagingBuffer = getStagingBuffer(); + + stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0); + directBuffer->setDataRevision(latestBuffer->getDataRevision()); + + latestBuffer = stagingBuffer; + } + + // if copyFromStorage returns true, the D3D buffer has been recreated + // and we should update our serial + if (directBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0)) + { + updateSerial(); + } + directBuffer->setDataRevision(latestBuffer->getDataRevision()); + } + + return directBuffer; +} + +Buffer11::BufferStorage11 *Buffer11::getLatestBufferStorage() const +{ + // Even though we iterate over all the direct buffers, it is expected that only + // 1 or 2 will be present. + BufferStorage11 *latestStorage = NULL; + DataRevision latestRevision = 0; + for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++) + { + BufferStorage11 *storage = it->second; + if (!latestStorage || storage->getDataRevision() > latestRevision) + { + latestStorage = storage; + latestRevision = storage->getDataRevision(); + } + } + + return latestStorage; +} + +Buffer11::NativeBuffer11 *Buffer11::getStagingBuffer() +{ + BufferStorage11 *stagingStorage = getBufferStorage(BUFFER_USAGE_STAGING); + + if (!stagingStorage) + { + // Out-of-memory + return NULL; + } + + ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, stagingStorage)); + return static_cast(stagingStorage); +} + +Buffer11::PackStorage11 *Buffer11::getPackStorage() +{ + BufferStorage11 *packStorage = getBufferStorage(BUFFER_USAGE_PIXEL_PACK); + + if (!packStorage) + { + // Out-of-memory + return NULL; + } + + ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, packStorage)); + return static_cast(packStorage); +} + +Buffer11::BufferStorage11::BufferStorage11(Renderer11 *renderer, BufferUsage usage) + : mRenderer(renderer), + mUsage(usage), + mRevision(0), + mBufferSize(0) +{ +} + +Buffer11::NativeBuffer11::NativeBuffer11(Renderer11 *renderer, BufferUsage usage) + : BufferStorage11(renderer, usage), + mNativeBuffer(NULL) +{ +} + +Buffer11::NativeBuffer11::~NativeBuffer11() +{ + SafeRelease(mNativeBuffer); +} + +// Returns true if it recreates the direct buffer +bool Buffer11::NativeBuffer11::copyFromStorage(BufferStorage11 *source, size_t sourceOffset, + size_t size, size_t destOffset) +{ + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + size_t requiredSize = sourceOffset + size; + bool createBuffer = !mNativeBuffer || mBufferSize < requiredSize; + + // (Re)initialize D3D buffer if needed + if (createBuffer) + { + bool preserveData = (destOffset > 0); + resize(source->getSize(), preserveData); + } + + if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK) + { + ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, source)); + + void *sourcePointer = source->map(sourceOffset, size, GL_MAP_READ_BIT); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT hr = context->Map(mNativeBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource); + UNUSED_ASSERTION_VARIABLE(hr); + ASSERT(SUCCEEDED(hr)); + + unsigned char *destPointer = static_cast(mappedResource.pData) + destOffset; + + // Offset bounds are validated at the API layer + ASSERT(sourceOffset + size <= destOffset + mBufferSize); + memcpy(destPointer, sourcePointer, size); + } + else + { + ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, source)); + + D3D11_BOX srcBox; + srcBox.left = sourceOffset; + srcBox.right = sourceOffset + size; + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, source)); + ID3D11Buffer *sourceBuffer = static_cast(source)->getNativeBuffer(); + + context->CopySubresourceRegion(mNativeBuffer, 0, destOffset, 0, 0, sourceBuffer, 0, &srcBox); + } + + return createBuffer; +} + +bool Buffer11::NativeBuffer11::resize(size_t size, bool preserveData) +{ + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + D3D11_BUFFER_DESC bufferDesc; + fillBufferDesc(&bufferDesc, mRenderer, mUsage, size); + + ID3D11Buffer *newBuffer; + HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer); + + if (FAILED(result)) + { + return gl::error(GL_OUT_OF_MEMORY, false); + } + + if (mNativeBuffer && preserveData) + { + // We don't call resize if the buffer is big enough already. + ASSERT(mBufferSize <= size); + + D3D11_BOX srcBox; + srcBox.left = 0; + srcBox.right = mBufferSize; + srcBox.top = 0; + srcBox.bottom = 1; + srcBox.front = 0; + srcBox.back = 1; + + context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeBuffer, 0, &srcBox); + } + + // No longer need the old buffer + SafeRelease(mNativeBuffer); + mNativeBuffer = newBuffer; + + mBufferSize = bufferDesc.ByteWidth; + + return true; +} + +void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, + BufferUsage usage, unsigned int bufferSize) +{ + bufferDesc->ByteWidth = bufferSize; + bufferDesc->MiscFlags = 0; + bufferDesc->StructureByteStride = 0; + + switch (usage) + { + case BUFFER_USAGE_STAGING: + bufferDesc->Usage = D3D11_USAGE_STAGING; + bufferDesc->BindFlags = 0; + bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + break; + + case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; + if (renderer->getMaxTransformFeedbackBuffers() > 0) + bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT; + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_INDEX: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_PIXEL_UNPACK: + bufferDesc->Usage = D3D11_USAGE_DEFAULT; + bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE; + bufferDesc->CPUAccessFlags = 0; + break; + + case BUFFER_USAGE_UNIFORM: + bufferDesc->Usage = D3D11_USAGE_DYNAMIC; + bufferDesc->BindFlags = D3D11_BIND_CONSTANT_BUFFER; + bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + + // Constant buffers must be of a limited size, and aligned to 16 byte boundaries + // For our purposes we ignore any buffer data past the maximum constant buffer size + bufferDesc->ByteWidth = roundUp(bufferDesc->ByteWidth, 16u); + bufferDesc->ByteWidth = std::min(bufferDesc->ByteWidth, renderer->getMaxUniformBufferSize()); + break; + + default: + UNREACHABLE(); + } +} + +void *Buffer11::NativeBuffer11::map(size_t offset, size_t length, GLbitfield access) +{ + ASSERT(mUsage == BUFFER_USAGE_STAGING); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(access); + UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0); + + HRESULT result = context->Map(mNativeBuffer, 0, d3dMapType, d3dMapFlag, &mappedResource); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + + return static_cast(mappedResource.pData) + offset; +} + +void Buffer11::NativeBuffer11::unmap() +{ + ASSERT(mUsage == BUFFER_USAGE_STAGING); + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + context->Unmap(mNativeBuffer, 0); +} + +Buffer11::PackStorage11::PackStorage11(Renderer11 *renderer) + : BufferStorage11(renderer, BUFFER_USAGE_PIXEL_PACK), + mStagingTexture(NULL), + mTextureFormat(DXGI_FORMAT_UNKNOWN), + mQueuedPackCommand(NULL), + mDataModified(false) +{ +} + +Buffer11::PackStorage11::~PackStorage11() +{ + SafeRelease(mStagingTexture); + SafeDelete(mQueuedPackCommand); +} + +bool Buffer11::PackStorage11::copyFromStorage(BufferStorage11 *source, size_t sourceOffset, + size_t size, size_t destOffset) +{ + UNIMPLEMENTED(); + return false; +} + +bool Buffer11::PackStorage11::resize(size_t size, bool preserveData) +{ + if (size != mBufferSize) + { + if (!mMemoryBuffer.resize(size)) + { + return false; + } + mBufferSize = size; + } + + return true; +} + +void *Buffer11::PackStorage11::map(size_t offset, size_t length, GLbitfield access) +{ + ASSERT(offset + length <= getSize()); + // TODO: fast path + // We might be able to optimize out one or more memcpy calls by detecting when + // and if D3D packs the staging texture memory identically to how we would fill + // the pack buffer according to the current pack state. + + flushQueuedPackCommand(); + mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0); + + return mMemoryBuffer.data() + offset; +} + +void Buffer11::PackStorage11::unmap() +{ + // No-op +} + +void Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms) +{ + flushQueuedPackCommand(); + mQueuedPackCommand = new PackPixelsParams(params); + + D3D11_TEXTURE2D_DESC textureDesc; + srcTexure->GetDesc(&textureDesc); + + if (mStagingTexture != NULL && + (mTextureFormat != textureDesc.Format || + mTextureSize.width != params.area.width || + mTextureSize.height != params.area.height)) + { + SafeRelease(mStagingTexture); + mTextureSize.width = 0; + mTextureSize.height = 0; + mTextureFormat = DXGI_FORMAT_UNKNOWN; + } + + if (mStagingTexture == NULL) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT hr; + + mTextureSize.width = params.area.width; + mTextureSize.height = params.area.height; + mTextureFormat = textureDesc.Format; + + D3D11_TEXTURE2D_DESC stagingDesc; + stagingDesc.Width = params.area.width; + stagingDesc.Height = params.area.height; + stagingDesc.MipLevels = 1; + stagingDesc.ArraySize = 1; + stagingDesc.Format = mTextureFormat; + stagingDesc.SampleDesc.Count = 1; + stagingDesc.SampleDesc.Quality = 0; + stagingDesc.Usage = D3D11_USAGE_STAGING; + stagingDesc.BindFlags = 0; + stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingDesc.MiscFlags = 0; + + hr = device->CreateTexture2D(&stagingDesc, NULL, &mStagingTexture); + ASSERT(SUCCEEDED(hr)); + } + + if (textureDesc.SampleDesc.Count > 1) + { + UNIMPLEMENTED(); + } + + ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext(); + D3D11_BOX srcBox; + srcBox.left = params.area.x; + srcBox.right = params.area.x + params.area.width; + srcBox.top = params.area.y; + srcBox.bottom = params.area.y + params.area.height; + srcBox.front = 0; + srcBox.back = 1; + + // Asynchronous copy + immediateContext->CopySubresourceRegion(mStagingTexture, 0, 0, 0, 0, srcTexure, srcSubresource, &srcBox); +} + +void Buffer11::PackStorage11::flushQueuedPackCommand() +{ + ASSERT(mMemoryBuffer.size() > 0); + + if (mQueuedPackCommand) + { + mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, mMemoryBuffer.data()); + SafeDelete(mQueuedPackCommand); + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h new file mode 100644 index 0000000000..e56be247c4 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h @@ -0,0 +1,106 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Buffer11.h: Defines the rx::Buffer11 class which implements rx::BufferImpl via rx::BufferD3D. + +#ifndef LIBGLESV2_RENDERER_BUFFER11_H_ +#define LIBGLESV2_RENDERER_BUFFER11_H_ + +#include "libGLESv2/renderer/d3d/BufferD3D.h" +#include "libGLESv2/renderer/d3d/MemoryBuffer.h" +#include "libGLESv2/angletypes.h" + +namespace rx +{ +class Renderer11; + +enum BufferUsage +{ + BUFFER_USAGE_STAGING, + BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK, + BUFFER_USAGE_INDEX, + BUFFER_USAGE_PIXEL_UNPACK, + BUFFER_USAGE_PIXEL_PACK, + BUFFER_USAGE_UNIFORM, +}; + +struct PackPixelsParams +{ + PackPixelsParams(); + PackPixelsParams(const gl::Rectangle &area, GLenum format, GLenum type, GLuint outputPitch, + const gl::PixelPackState &pack, ptrdiff_t offset); + + gl::Rectangle area; + GLenum format; + GLenum type; + GLuint outputPitch; + gl::Buffer *packBuffer; + gl::PixelPackState pack; + ptrdiff_t offset; +}; + +typedef size_t DataRevision; + +class Buffer11 : public BufferD3D +{ + public: + Buffer11(rx::Renderer11 *renderer); + virtual ~Buffer11(); + + static Buffer11 *makeBuffer11(BufferImpl *buffer); + + ID3D11Buffer *getBuffer(BufferUsage usage); + ID3D11ShaderResourceView *getSRV(DXGI_FORMAT srvFormat); + bool isMapped() const { return mMappedStorage != NULL; } + void 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 Renderer* getRenderer(); + + // BufferImpl implementation + virtual void 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 void markTransformFeedbackUsage(); + + private: + DISALLOW_COPY_AND_ASSIGN(Buffer11); + + class BufferStorage11; + class NativeBuffer11; + class PackStorage11; + + rx::Renderer11 *mRenderer; + size_t mSize; + + BufferStorage11 *mMappedStorage; + + std::map mBufferStorages; + + typedef std::pair BufferSRVPair; + std::map mBufferResourceViews; + + MemoryBuffer mResolvedData; + DataRevision mResolvedDataRevision; + unsigned int mReadUsageCount; + + void markBufferUsage(); + NativeBuffer11 *getStagingBuffer(); + PackStorage11 *getPackStorage(); + + BufferStorage11 *getBufferStorage(BufferUsage usage); + BufferStorage11 *getLatestBufferStorage() const; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp new file mode 100644 index 0000000000..8db5ea27c1 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp @@ -0,0 +1,568 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Clear11.cpp: Framebuffer clear utility class. + +#include "libGLESv2/renderer/d3d/d3d11/Clear11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" + +#include "libGLESv2/formatutils.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" + +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloatvs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloatps.h" + +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuintvs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuintps.h" + +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsintvs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsintps.h" + +namespace rx +{ + +template +static void ApplyVertices(const gl::Extents &framebufferSize, const gl::Rectangle *scissor, const gl::Color &color, float depth, void *buffer) +{ + d3d11::PositionDepthColorVertex *vertices = reinterpret_cast*>(buffer); + + float depthClear = gl::clamp01(depth); + float left = -1.0f; + float right = 1.0f; + float top = -1.0f; + float bottom = 1.0f; + + // Clip the quad coordinates to the scissor if needed + if (scissor != NULL) + { + left = std::max(left, (scissor->x / float(framebufferSize.width)) * 2.0f - 1.0f); + right = std::min(right, ((scissor->x + scissor->width) / float(framebufferSize.width)) * 2.0f - 1.0f); + top = std::max(top, ((framebufferSize.height - scissor->y - scissor->height) / float(framebufferSize.height)) * 2.0f - 1.0f); + bottom = std::min(bottom, ((framebufferSize.height - scissor->y) / float(framebufferSize.height)) * 2.0f - 1.0f); + } + + d3d11::SetPositionDepthColorVertex(vertices + 0, left, bottom, depthClear, color); + d3d11::SetPositionDepthColorVertex(vertices + 1, left, top, depthClear, color); + d3d11::SetPositionDepthColorVertex(vertices + 2, right, bottom, depthClear, color); + d3d11::SetPositionDepthColorVertex(vertices + 3, right, top, depthClear, color); +} + +template +Clear11::ClearShader Clear11::CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE (&vsByteCode)[vsSize], const BYTE (&psByteCode)[psSize]) +{ + HRESULT result; + + ClearShader shader = { 0 }; + + D3D11_INPUT_ELEMENT_DESC quadLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, colorType, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + result = device->CreateInputLayout(quadLayout, ArraySize(quadLayout), vsByteCode, vsSize, &shader.inputLayout); + ASSERT(SUCCEEDED(result)); + + result = device->CreateVertexShader(vsByteCode, vsSize, NULL, &shader.vertexShader); + ASSERT(SUCCEEDED(result)); + + result = device->CreatePixelShader(psByteCode, psSize, NULL, &shader.pixelShader); + ASSERT(SUCCEEDED(result)); + + return shader; +} + +Clear11::Clear11(Renderer11 *renderer) + : mRenderer(renderer), mClearBlendStates(StructLessThan), mClearDepthStencilStates(StructLessThan), + mVertexBuffer(NULL), mRasterizerState(NULL) +{ + HRESULT result; + ID3D11Device *device = renderer->getDevice(); + + D3D11_BUFFER_DESC vbDesc; + vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex) * 4; + vbDesc.Usage = D3D11_USAGE_DYNAMIC; + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vbDesc.MiscFlags = 0; + vbDesc.StructureByteStride = 0; + + result = device->CreateBuffer(&vbDesc, NULL, &mVertexBuffer); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mVertexBuffer, "Clear11 masked clear vertex buffer"); + + D3D11_RASTERIZER_DESC rsDesc; + rsDesc.FillMode = D3D11_FILL_SOLID; + rsDesc.CullMode = D3D11_CULL_NONE; + rsDesc.FrontCounterClockwise = FALSE; + rsDesc.DepthBias = 0; + rsDesc.DepthBiasClamp = 0.0f; + rsDesc.SlopeScaledDepthBias = 0.0f; + rsDesc.DepthClipEnable = mRenderer->isLevel9(); + rsDesc.ScissorEnable = FALSE; + rsDesc.MultisampleEnable = FALSE; + rsDesc.AntialiasedLineEnable = FALSE; + + result = device->CreateRasterizerState(&rsDesc, &mRasterizerState); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state"); + + mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat); + if (mRenderer->isLevel9()) { + mUintClearShader = { 0 }; + mIntClearShader = { 0 }; + return; + } + + mUintClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT, g_VS_ClearUint, g_PS_ClearUint ); + mIntClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT, g_VS_ClearSint, g_PS_ClearSint ); +} + +Clear11::~Clear11() +{ + for (ClearBlendStateMap::iterator i = mClearBlendStates.begin(); i != mClearBlendStates.end(); i++) + { + SafeRelease(i->second); + } + mClearBlendStates.clear(); + + SafeRelease(mFloatClearShader.inputLayout); + SafeRelease(mFloatClearShader.vertexShader); + SafeRelease(mFloatClearShader.pixelShader); + + SafeRelease(mUintClearShader.inputLayout); + SafeRelease(mUintClearShader.vertexShader); + SafeRelease(mUintClearShader.pixelShader); + + SafeRelease(mIntClearShader.inputLayout); + SafeRelease(mIntClearShader.vertexShader); + SafeRelease(mIntClearShader.pixelShader); + + for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin(); i != mClearDepthStencilStates.end(); i++) + { + SafeRelease(i->second); + } + mClearDepthStencilStates.clear(); + + SafeRelease(mVertexBuffer); + SafeRelease(mRasterizerState); +} + +void Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) +{ + // First determine if a scissored clear is needed, this will always require drawing a quad. + // + // Otherwise, iterate over the color buffers which require clearing and determine if they can be + // cleared with ID3D11DeviceContext::ClearRenderTargetView... This requires: + // 1) The render target is being cleared to a float value (will be cast to integer when clearing integer + // render targets as expected but does not work the other way around) + // 2) The format of the render target has no color channels that are currently masked out. + // Clear the easy-to-clear buffers on the spot and accumulate the ones that require special work. + // + // Also determine if the depth stencil can be cleared with ID3D11DeviceContext::ClearDepthStencilView + // by checking if the stencil write mask covers the entire stencil. + // + // To clear the remaining buffers, quads must be drawn containing an int, uint or float vertex color + // attribute. + + gl::Extents framebufferSize; + if (frameBuffer->getFirstColorbuffer() != NULL) + { + gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer(); + framebufferSize.width = attachment->getWidth(); + framebufferSize.height = attachment->getHeight(); + framebufferSize.depth = 1; + } + else if (frameBuffer->getDepthOrStencilbuffer() != NULL) + { + gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer(); + framebufferSize.width = attachment->getWidth(); + framebufferSize.height = attachment->getHeight(); + framebufferSize.depth = 1; + } + else + { + UNREACHABLE(); + return; + } + + if (clearParams.scissorEnabled && (clearParams.scissor.x >= framebufferSize.width || + clearParams.scissor.y >= framebufferSize.height || + clearParams.scissor.x + clearParams.scissor.width <= 0 || + clearParams.scissor.y + clearParams.scissor.height <= 0)) + { + // Scissor is enabled and the scissor rectangle is outside the renderbuffer + return; + } + + bool needScissoredClear = clearParams.scissorEnabled && (clearParams.scissor.x > 0 || clearParams.scissor.y > 0 || + clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width || + clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height); + + std::vector maskedClearRenderTargets; + RenderTarget11* maskedClearDepthStencil = NULL; + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + if (clearParams.clearColor[colorAttachment] && frameBuffer->isEnabledColorAttachment(colorAttachment)) + { + gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(colorAttachment); + if (attachment) + { + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(attachment->getRenderTarget()); + if (!renderTarget) + { + ERR("Render target pointer unexpectedly null."); + return; + } + + GLenum internalFormat = attachment->getInternalFormat(); + GLenum actualFormat = attachment->getActualFormat(); + GLenum componentType = gl::GetComponentType(internalFormat); + if (clearParams.colorClearType == GL_FLOAT && + !(componentType == GL_FLOAT || componentType == GL_UNSIGNED_NORMALIZED || 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); + } + + 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)) + { + // 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)) + { + // A scissored or masked clear is required + MaskedRenderTarget maskAndRt; + bool clearColor = clearParams.clearColor[colorAttachment]; + maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed); + maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen); + maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue); + maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha); + maskAndRt.renderTarget = renderTarget; + maskedClearRenderTargets.push_back(maskAndRt); + } + else + { + // ID3D11DeviceContext::ClearRenderTargetView is possible + + ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); + if (!framebufferRTV) + { + ERR("Render target view pointer unexpectedly null."); + return; + } + + // 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), + }; + + deviceContext->ClearRenderTargetView(framebufferRTV, clearValues); + } + } + } + } + + if (clearParams.clearDepth || clearParams.clearStencil) + { + gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer(); + if (attachment) + { + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(attachment->getDepthStencil()); + if (!renderTarget) + { + ERR("Depth stencil render target pointer unexpectedly null."); + return; + } + + GLenum actualFormat = attachment->getActualFormat(); + + unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << gl::GetStencilBits(actualFormat)) - 1 : 0; + bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + + if (needScissoredClear || needMaskedStencilClear) + { + maskedClearDepthStencil = renderTarget; + } + else + { + ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); + if (!framebufferDSV) + { + ERR("Depth stencil view pointer unexpectedly null."); + return; + } + + UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) | + (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0); + FLOAT depthClear = gl::clamp01(clearParams.depthClearValue); + UINT8 stencilClear = clearParams.stencilClearValue & 0xFF; + + deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); + } + } + } + + if (maskedClearRenderTargets.size() > 0 || maskedClearDepthStencil) + { + // To clear the render targets and depth stencil in one pass: + // + // Render a quad clipped to the scissor rectangle which draws the clear color and a blend + // state that will perform the required color masking. + // + // The quad's depth is equal to the depth clear value with a depth stencil state that + // will enable or disable depth test/writes if the depth buffer should be cleared or not. + // + // The rasterizer state's stencil is set to always pass or fail based on if the stencil + // should be cleared or not with a stencil write mask of the stencil clear value. + // + // ====================================================================================== + // + // Luckily, the gl spec (ES 3.0.2 pg 183) states that the results of clearing a render- + // buffer that is not normalized fixed point or floating point with floating point values + // are undefined so we can just write floats to them and D3D11 will bit cast them to + // integers. + // + // Also, we don't have to worry about attempting to clear a normalized fixed/floating point + // buffer with integer values because there is no gl API call which would allow it, + // glClearBuffer* calls only clear a single renderbuffer at a time which is verified to + // be a compatible clear type. + + // Bind all the render targets which need clearing + ASSERT(maskedClearRenderTargets.size() <= mRenderer->getRendererCaps().maxDrawBuffers); + std::vector rtvs(maskedClearRenderTargets.size()); + for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++) + { + RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget; + ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView(); + if (!rtv) + { + ERR("Render target view unexpectedly null."); + return; + } + + rtvs[i] = rtv; + } + ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : NULL; + + ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets); + const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + const UINT sampleMask = 0xFFFFFFFF; + + ID3D11DepthStencilState *dsState = getDepthStencilState(clearParams); + const UINT stencilClear = clearParams.stencilClearValue & 0xFF; + + // Set the vertices + UINT vertexStride = 0; + const UINT startIdx = 0; + const ClearShader* shader = NULL; + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = deviceContext->Map(mVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result); + return; + } + + const gl::Rectangle *scissorPtr = clearParams.scissorEnabled ? &clearParams.scissor : NULL; + switch (clearParams.colorClearType) + { + case GL_FLOAT: + ApplyVertices(framebufferSize, scissorPtr, clearParams.colorFClearValue, clearParams.depthClearValue, mappedResource.pData); + vertexStride = sizeof(d3d11::PositionDepthColorVertex); + shader = &mFloatClearShader; + break; + + case GL_UNSIGNED_INT: + ApplyVertices(framebufferSize, scissorPtr, clearParams.colorUIClearValue, clearParams.depthClearValue, mappedResource.pData); + vertexStride = sizeof(d3d11::PositionDepthColorVertex); + shader = &mUintClearShader; + break; + + case GL_INT: + ApplyVertices(framebufferSize, scissorPtr, clearParams.colorIClearValue, clearParams.depthClearValue, mappedResource.pData); + vertexStride = sizeof(d3d11::PositionDepthColorVertex); + shader = &mIntClearShader; + break; + + default: + UNREACHABLE(); + break; + } + + deviceContext->Unmap(mVertexBuffer, 0); + + // Set the viewport to be the same size as the framebuffer + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = framebufferSize.width; + viewport.Height = framebufferSize.height; + viewport.MinDepth = 0; + viewport.MaxDepth = 1; + deviceContext->RSSetViewports(1, &viewport); + + // Apply state + deviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); + deviceContext->OMSetDepthStencilState(dsState, stencilClear); + deviceContext->RSSetState(mRasterizerState); + + // Apply shaders + deviceContext->IASetInputLayout(shader->inputLayout); + deviceContext->VSSetShader(shader->vertexShader, NULL, 0); + deviceContext->PSSetShader(shader->pixelShader, NULL, 0); + deviceContext->GSSetShader(NULL, NULL, 0); + + // Apply vertex buffer + deviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &vertexStride, &startIdx); + deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + + // Apply render targets + deviceContext->OMSetRenderTargets(rtvs.size(), (rtvs.empty() ? NULL : &rtvs[0]), dsv); + + // Draw the clear quad + deviceContext->Draw(4, 0); + + // Clean up + mRenderer->markAllStateDirty(); + } +} + +ID3D11BlendState *Clear11::getBlendState(const std::vector& rts) +{ + ClearBlendInfo blendKey = { 0 }; + for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + { + if (i < rts.size()) + { + RenderTarget11 *rt = rts[i].renderTarget; + GLint internalFormat = 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); + } + else + { + blendKey.maskChannels[i][0] = false; + blendKey.maskChannels[i][1] = false; + blendKey.maskChannels[i][2] = false; + blendKey.maskChannels[i][3] = false; + } + } + + ClearBlendStateMap::const_iterator i = mClearBlendStates.find(blendKey); + if (i != mClearBlendStates.end()) + { + return i->second; + } + else + { + D3D11_BLEND_DESC blendDesc = { 0 }; + blendDesc.AlphaToCoverageEnable = FALSE; + blendDesc.IndependentBlendEnable = (rts.size() > 1) ? TRUE : FALSE; + + for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + { + blendDesc.RenderTarget[i].BlendEnable = FALSE; + blendDesc.RenderTarget[i].RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendKey.maskChannels[i][0], + blendKey.maskChannels[i][1], + blendKey.maskChannels[i][2], + blendKey.maskChannels[i][3]); + } + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11BlendState* blendState = NULL; + HRESULT result = device->CreateBlendState(&blendDesc, &blendState); + if (FAILED(result) || !blendState) + { + ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); + return NULL; + } + + mClearBlendStates[blendKey] = blendState; + + return blendState; + } +} + +ID3D11DepthStencilState *Clear11::getDepthStencilState(const gl::ClearParameters &clearParams) +{ + ClearDepthStencilInfo dsKey = { 0 }; + dsKey.clearDepth = clearParams.clearDepth; + dsKey.clearStencil = clearParams.clearStencil; + dsKey.stencilWriteMask = clearParams.stencilWriteMask & 0xFF; + + ClearDepthStencilStateMap::const_iterator i = mClearDepthStencilStates.find(dsKey); + if (i != mClearDepthStencilStates.end()) + { + return i->second; + } + else + { + D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 }; + dsDesc.DepthEnable = dsKey.clearDepth ? TRUE : FALSE; + dsDesc.DepthWriteMask = dsKey.clearDepth ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; + dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + dsDesc.StencilEnable = dsKey.clearStencil ? TRUE : FALSE; + dsDesc.StencilReadMask = 0; + dsDesc.StencilWriteMask = dsKey.stencilWriteMask; + dsDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + dsDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_REPLACE; + dsDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DepthStencilState* dsState = NULL; + HRESULT result = device->CreateDepthStencilState(&dsDesc, &dsState); + if (FAILED(result) || !dsState) + { + ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); + return NULL; + } + + mClearDepthStencilStates[dsKey] = dsState; + + return dsState; + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h new file mode 100644 index 0000000000..0cb9a85a6d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h @@ -0,0 +1,83 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Clear11.h: Framebuffer clear utility class. + +#ifndef LIBGLESV2_RENDERER_CLEAR11_H_ +#define LIBGLESV2_RENDERER_CLEAR11_H_ + +#include "libGLESv2/angletypes.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer11; +class RenderTarget11; + +class Clear11 +{ + public: + explicit Clear11(Renderer11 *renderer); + ~Clear11(); + + // Clears the framebuffer with the supplied clear parameters, assumes that the framebuffer is currently applied. + void clearFramebuffer(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); + + private: + Renderer11 *mRenderer; + + struct ClearBlendInfo + { + bool maskChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; + }; + typedef bool (*ClearBlendInfoComparisonFunction)(const ClearBlendInfo&, const ClearBlendInfo &); + typedef std::map ClearBlendStateMap; + ClearBlendStateMap mClearBlendStates; + + struct MaskedRenderTarget + { + bool colorMask[4]; + RenderTarget11 *renderTarget; + }; + + ID3D11BlendState *getBlendState(const std::vector &rts); + + struct ClearShader + { + ID3D11InputLayout *inputLayout; + ID3D11VertexShader *vertexShader; + ID3D11PixelShader *pixelShader; + }; + ClearShader mFloatClearShader; + ClearShader mUintClearShader; + ClearShader mIntClearShader; + + template + static ClearShader CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE (&vsByteCode)[vsSize], const BYTE (&psByteCode)[psSize]); + + struct ClearDepthStencilInfo + { + bool clearDepth; + bool clearStencil; + UINT8 stencilWriteMask; + }; + typedef bool (*ClearDepthStencilInfoComparisonFunction)(const ClearDepthStencilInfo&, const ClearDepthStencilInfo &); + typedef std::map ClearDepthStencilStateMap; + ClearDepthStencilStateMap mClearDepthStencilStates; + + ID3D11DepthStencilState *getDepthStencilState(const gl::ClearParameters &clearParams); + + ID3D11Buffer *mVertexBuffer; + ID3D11RasterizerState *mRasterizerState; +}; + +} + +#endif // LIBGLESV2_RENDERER_CLEAR11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp new file mode 100644 index 0000000000..8698776650 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp @@ -0,0 +1,71 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Fence11.cpp: Defines the rx::Fence11 class which implements rx::FenceImpl. + +#include "libGLESv2/renderer/d3d/d3d11/Fence11.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ + +Fence11::Fence11(rx::Renderer11 *renderer) +{ + mRenderer = renderer; + mQuery = NULL; +} + +Fence11::~Fence11() +{ + SafeRelease(mQuery); +} + +bool Fence11::isSet() const +{ + return mQuery != NULL; +} + +void Fence11::set() +{ + if (!mQuery) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.MiscFlags = 0; + + if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + mRenderer->getDeviceContext()->End(mQuery); +} + +bool Fence11::test(bool flushCommandBuffer) +{ + ASSERT(mQuery); + + UINT getDataFlags = (flushCommandBuffer ? 0 : D3D11_ASYNC_GETDATA_DONOTFLUSH); + HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, getDataFlags); + + if (mRenderer->isDeviceLost()) + { + return gl::error(GL_OUT_OF_MEMORY, true); + } + + ASSERT(result == S_OK || result == S_FALSE); + return (result == S_OK); +} + +bool Fence11::hasError() const +{ + return mRenderer->isDeviceLost(); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h new file mode 100644 index 0000000000..50c7621776 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Fence11.h: Defines the rx::Fence11 class which implements rx::FenceImpl. + +#ifndef LIBGLESV2_RENDERER_Fence11_H_ +#define LIBGLESV2_RENDERER_Fence11_H_ + +#include "libGLESv2/renderer/FenceImpl.h" + +namespace rx +{ +class Renderer11; + +class Fence11 : public FenceImpl +{ + public: + explicit Fence11(rx::Renderer11 *renderer); + virtual ~Fence11(); + + bool isSet() const; + void set(); + bool test(bool flushCommandBuffer); + bool hasError() const; + + private: + DISALLOW_COPY_AND_ASSIGN(Fence11); + + rx::Renderer11 *mRenderer; + ID3D11Query *mQuery; +}; + +} + +#endif // LIBGLESV2_RENDERER_FENCE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp new file mode 100644 index 0000000000..2165bec305 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp @@ -0,0 +1,460 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image11.h: Implements the rx::Image11 class, which acts as the interface to +// the actual underlying resources of a Texture + +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Image11.h" +#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.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 +{ + +Image11::Image11() +{ + mStagingTexture = NULL; + mRenderer = NULL; + mDXGIFormat = DXGI_FORMAT_UNKNOWN; +} + +Image11::~Image11() +{ + SafeRelease(mStagingTexture); +} + +Image11 *Image11::makeImage11(Image *img) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::Image11*, img)); + return static_cast(img); +} + +void Image11::generateMipmap(Image11 *dest, Image11 *src) +{ + ASSERT(src->getDXGIFormat() == dest->getDXGIFormat()); + ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth()); + ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight()); + + MipGenerationFunction mipFunction = d3d11::GetMipGenerationFunction(src->getDXGIFormat()); + ASSERT(mipFunction != NULL); + + D3D11_MAPPED_SUBRESOURCE destMapped; + HRESULT destMapResult = dest->map(D3D11_MAP_WRITE, &destMapped); + if (FAILED(destMapResult)) + { + ERR("Failed to map destination image for mip map generation. HRESULT:0x%X", destMapResult); + return; + } + + D3D11_MAPPED_SUBRESOURCE srcMapped; + HRESULT srcMapResult = src->map(D3D11_MAP_READ, &srcMapped); + if (FAILED(srcMapResult)) + { + ERR("Failed to map source image for mip map generation. HRESULT:0x%X", srcMapResult); + + dest->unmap(); + return; + } + + 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); + + dest->unmap(); + src->unmap(); + + dest->markDirty(); +} + +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))); +} + +bool Image11::copyToStorage(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); + return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, 0, width, height, 1); +} + +bool Image11::copyToStorage(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); + return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, face, xoffset, yoffset, 0, width, height, 1); +} + +bool Image11::copyToStorage(TextureStorageInterface3D *storage, int level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth) +{ + TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage->getStorageInstance()); + return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, zoffset, width, height, depth); +} + +bool Image11::copyToStorage(TextureStorageInterface2DArray *storage, int level, GLint xoffset, GLint yoffset, GLint arrayLayer, 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); +} + +bool Image11::redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) +{ + if (mWidth != width || + mHeight != height || + mInternalFormat != internalformat || + forceRelease) + { + mRenderer = Renderer11::makeRenderer11(renderer); + + mWidth = width; + mHeight = height; + mDepth = depth; + mInternalFormat = 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; + + SafeRelease(mStagingTexture); + mDirty = gl_d3d11::RequiresTextureDataInitialization(mInternalFormat); + + return true; + } + + return false; +} + +DXGI_FORMAT Image11::getDXGIFormat() const +{ + // this should only happen if the image hasn't been redefined first + // which would be a bug by the caller + ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN); + + return mDXGIFormat; +} + +// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input +// into the target pixel rectangle. +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); + + LoadImageFunction loadFunction = d3d11::GetImageLoadFunction(mInternalFormat, type); + ASSERT(loadFunction != NULL); + + D3D11_MAPPED_SUBRESOURCE mappedImage; + HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); + if (FAILED(result)) + { + ERR("Could not map image for loading."); + return; + } + + uint8_t* offsetMappedData = (reinterpret_cast(mappedImage.pData) + (yoffset * mappedImage.RowPitch + xoffset * outputPixelSize + zoffset * mappedImage.DepthPitch)); + loadFunction(width, height, depth, + reinterpret_cast(input), inputRowPitch, inputDepthPitch, + offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); + + unmap(); +} + +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); + + GLuint outputPixelSize = d3d11::GetFormatPixelBytes(mDXGIFormat); + GLuint outputBlockWidth = d3d11::GetBlockWidth(mDXGIFormat); + GLuint outputBlockHeight = d3d11::GetBlockHeight(mDXGIFormat); + + ASSERT(xoffset % outputBlockWidth == 0); + ASSERT(yoffset % outputBlockHeight == 0); + + LoadImageFunction loadFunction = d3d11::GetImageLoadFunction(mInternalFormat, GL_UNSIGNED_BYTE); + ASSERT(loadFunction != NULL); + + D3D11_MAPPED_SUBRESOURCE mappedImage; + HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); + if (FAILED(result)) + { + ERR("Could not map image for loading."); + return; + } + + uint8_t* offsetMappedData = reinterpret_cast(mappedImage.pData) + ((yoffset / outputBlockHeight) * mappedImage.RowPitch + + (xoffset / outputBlockWidth) * outputPixelSize + + zoffset * mappedImage.DepthPitch); + + loadFunction(width, height, depth, + reinterpret_cast(input), inputRowPitch, inputDepthPitch, + offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch); + + unmap(); +} + +void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer(); + + if (colorbuffer && colorbuffer->getActualFormat() == mActualFormat) + { + // No conversion needed-- use copyback fastpath + ID3D11Texture2D *colorBufferTexture = NULL; + unsigned int subresourceIndex = 0; + + if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) + { + D3D11_TEXTURE2D_DESC textureDesc; + colorBufferTexture->GetDesc(&textureDesc); + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + ID3D11Texture2D* srcTex = NULL; + if (textureDesc.SampleDesc.Count > 1) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = textureDesc.Width; + resolveDesc.Height = textureDesc.Height; + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = textureDesc.Format; + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = D3D11_USAGE_DEFAULT; + resolveDesc.BindFlags = 0; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex); + if (FAILED(result)) + { + ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result); + return; + } + + deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format); + subresourceIndex = 0; + } + else + { + srcTex = colorBufferTexture; + srcTex->AddRef(); + } + + D3D11_BOX srcBox; + srcBox.left = x; + srcBox.right = x + width; + srcBox.top = y; + srcBox.bottom = y + height; + srcBox.front = 0; + srcBox.back = 1; + + deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, zoffset, srcTex, subresourceIndex, &srcBox); + + SafeRelease(srcTex); + SafeRelease(colorBufferTexture); + } + } + else + { + // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels + D3D11_MAPPED_SUBRESOURCE mappedImage; + HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); + if (FAILED(result)) + { + ERR("Failed to map texture for Image11::copy, HRESULT: 0x%X.", result); + return; + } + + // 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; + + GLenum format = gl::GetFormat(mInternalFormat); + GLenum type = gl::GetType(mInternalFormat); + + mRenderer->readPixels(source, x, y, width, height, format, type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset); + + unmap(); + } +} + +ID3D11Resource *Image11::getStagingTexture() +{ + createStagingTexture(); + + return mStagingTexture; +} + +unsigned int Image11::getStagingSubresource() +{ + createStagingTexture(); + + return mStagingSubresource; +} + +void Image11::createStagingTexture() +{ + if (mStagingTexture) + { + return; + } + + const DXGI_FORMAT dxgiFormat = getDXGIFormat(); + + if (mWidth > 0 && mHeight > 0 && mDepth > 0) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + int lodOffset = 1; + GLsizei width = mWidth; + GLsizei height = mHeight; + + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, dxgiFormat, &width, &height, &lodOffset); + + if (mTarget == GL_TEXTURE_3D) + { + ID3D11Texture3D *newTexture = NULL; + + D3D11_TEXTURE3D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.Depth = mDepth; + desc.MipLevels = lodOffset + 1; + desc.Format = dxgiFormat; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + + if (gl_d3d11::RequiresTextureDataInitialization(mInternalFormat)) + { + std::vector initialData; + std::vector< std::vector > textureData; + d3d11::GenerateInitialTextureData(mInternalFormat, width, height, mDepth, + lodOffset + 1, &initialData, &textureData); + + result = device->CreateTexture3D(&desc, initialData.data(), &newTexture); + } + else + { + result = device->CreateTexture3D(&desc, NULL, &newTexture); + } + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + return gl::error(GL_OUT_OF_MEMORY); + } + + mStagingTexture = newTexture; + mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); + } + else if (mTarget == GL_TEXTURE_2D || mTarget == GL_TEXTURE_2D_ARRAY || mTarget == GL_TEXTURE_CUBE_MAP) + { + ID3D11Texture2D *newTexture = NULL; + + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.MipLevels = lodOffset + 1; + desc.ArraySize = 1; + desc.Format = dxgiFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_STAGING; + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.MiscFlags = 0; + + if (gl_d3d11::RequiresTextureDataInitialization(mInternalFormat)) + { + std::vector initialData; + std::vector< std::vector > textureData; + d3d11::GenerateInitialTextureData(mInternalFormat, width, height, 1, + lodOffset + 1, &initialData, &textureData); + + result = device->CreateTexture2D(&desc, initialData.data(), &newTexture); + } + else + { + result = device->CreateTexture2D(&desc, NULL, &newTexture); + } + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + return gl::error(GL_OUT_OF_MEMORY); + } + + mStagingTexture = newTexture; + mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); + } + else + { + UNREACHABLE(); + } + } + + mDirty = false; +} + +HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) +{ + createStagingTexture(); + + HRESULT result = E_FAIL; + + if (mStagingTexture) + { + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + result = deviceContext->Map(mStagingTexture, mStagingSubresource, mapType, 0, map); + + // this can fail if the device is removed (from TDR) + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + } + else if (SUCCEEDED(result)) + { + mDirty = true; + } + } + + return result; +} + +void Image11::unmap() +{ + if (mStagingTexture) + { + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + deviceContext->Unmap(mStagingTexture, mStagingSubresource); + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h new file mode 100644 index 0000000000..7d873a2794 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h @@ -0,0 +1,77 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image11.h: Defines the rx::Image11 class, which acts as the interface to +// the actual underlying resources of a Texture + +#ifndef LIBGLESV2_RENDERER_IMAGE11_H_ +#define LIBGLESV2_RENDERER_IMAGE11_H_ + +#include "libGLESv2/renderer/d3d/ImageD3D.h" + +#include "common/debug.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer; +class Renderer11; +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; + +class Image11 : public ImageD3D +{ + public: + Image11(); + virtual ~Image11(); + + static Image11 *makeImage11(Image *img); + + static void generateMipmap(Image11 *dest, Image11 *src); + + 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 redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease); + + DXGI_FORMAT getDXGIFormat() const; + + virtual void loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLint unpackAlignment, GLenum type, const void *input); + virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + const void *input); + + virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + + protected: + HRESULT map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); + void unmap(); + + private: + DISALLOW_COPY_AND_ASSIGN(Image11); + + ID3D11Resource *getStagingTexture(); + unsigned int getStagingSubresource(); + void createStagingTexture(); + + Renderer11 *mRenderer; + + DXGI_FORMAT mDXGIFormat; + ID3D11Resource *mStagingTexture; + unsigned int mStagingSubresource; +}; + +} + +#endif // LIBGLESV2_RENDERER_IMAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp new file mode 100644 index 0000000000..03e4e6611b --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp @@ -0,0 +1,175 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation. + +#include "libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ + +IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) +{ + mBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; +} + +IndexBuffer11::~IndexBuffer11() +{ + SafeRelease(mBuffer); +} + +bool IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) +{ + SafeRelease(mBuffer); + + updateSerial(); + + if (bufferSize > 0) + { + ID3D11Device* dxDevice = mRenderer->getDevice(); + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = bufferSize; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); + if (FAILED(result)) + { + return false; + } + } + + mBufferSize = bufferSize; + mIndexType = indexType; + mDynamicUsage = dynamic; + + return true; +} + +IndexBuffer11 *IndexBuffer11::makeIndexBuffer11(IndexBuffer *indexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer11*, indexBuffer)); + return static_cast(indexBuffer); +} + +bool IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) +{ + if (mBuffer) + { + // Check for integer overflows and out-out-bounds map requests + if (offset + size < offset || offset + size > mBufferSize) + { + ERR("Index buffer map range is not inside the buffer."); + return false; + } + + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Index buffer map failed with error 0x%08x", result); + return false; + } + + *outMappedMemory = reinterpret_cast(mappedResource.pData) + offset; + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +bool IndexBuffer11::unmapBuffer() +{ + if (mBuffer) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + dxContext->Unmap(mBuffer, 0); + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +GLenum IndexBuffer11::getIndexType() const +{ + return mIndexType; +} + +unsigned int IndexBuffer11::getBufferSize() const +{ + return mBufferSize; +} + +bool IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType) +{ + if (bufferSize > mBufferSize || indexType != mIndexType) + { + return initialize(bufferSize, indexType, mDynamicUsage); + } + else + { + return true; + } +} + +bool IndexBuffer11::discard() +{ + if (mBuffer) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Index buffer map failed with error 0x%08x", result); + return false; + } + + dxContext->Unmap(mBuffer, 0); + + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +DXGI_FORMAT IndexBuffer11::getIndexFormat() const +{ + switch (mIndexType) + { + case GL_UNSIGNED_BYTE: return DXGI_FORMAT_R16_UINT; + case GL_UNSIGNED_SHORT: return DXGI_FORMAT_R16_UINT; + case GL_UNSIGNED_INT: return DXGI_FORMAT_R32_UINT; + default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; + } +} + +ID3D11Buffer *IndexBuffer11::getBuffer() const +{ + return mBuffer; +} + +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h new file mode 100644 index 0000000000..e821b7f3d1 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// IndexBuffer11.h: Defines the D3D11 IndexBuffer implementation. + +#ifndef LIBGLESV2_RENDERER_INDEXBUFFER11_H_ +#define LIBGLESV2_RENDERER_INDEXBUFFER11_H_ + +#include "libGLESv2/renderer/d3d/IndexBuffer.h" + +namespace rx +{ +class Renderer11; + +class IndexBuffer11 : public IndexBuffer +{ + public: + explicit IndexBuffer11(Renderer11 *const renderer); + virtual ~IndexBuffer11(); + + virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); + + static IndexBuffer11 *makeIndexBuffer11(IndexBuffer *indexBuffer); + + virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); + virtual bool unmapBuffer(); + + virtual GLenum getIndexType() const; + virtual unsigned int getBufferSize() const; + virtual bool setSize(unsigned int bufferSize, GLenum indexType); + + virtual bool discard(); + + DXGI_FORMAT getIndexFormat() const; + ID3D11Buffer *getBuffer() const; + + private: + DISALLOW_COPY_AND_ASSIGN(IndexBuffer11); + + rx::Renderer11 *const mRenderer; + + ID3D11Buffer *mBuffer; + unsigned int mBufferSize; + GLenum mIndexType; + bool mDynamicUsage; +}; + +} + +#endif // LIBGLESV2_RENDERER_INDEXBUFFER11_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp new file mode 100644 index 0000000000..3536fafac9 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp @@ -0,0 +1,248 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches +// D3D11 input layouts. + +#include "libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h" +#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libGLESv2/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" + +namespace rx +{ + +static void GetInputLayout(const TranslatedAttribute translatedAttributes[gl::MAX_VERTEX_ATTRIBS], + gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]) +{ + for (unsigned int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++) + { + const TranslatedAttribute &translatedAttribute = translatedAttributes[attributeIndex]; + + if (translatedAttributes[attributeIndex].active) + { + inputLayout[attributeIndex] = gl::VertexFormat(*translatedAttribute.attribute, + translatedAttribute.currentValueType); + } + } +} + +const unsigned int InputLayoutCache::kMaxInputLayouts = 1024; + +InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts) +{ + mCounter = 0; + mDevice = NULL; + mDeviceContext = NULL; + mCurrentIL = NULL; + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mCurrentBuffers[i] = NULL; + mCurrentVertexStrides[i] = -1; + mCurrentVertexOffsets[i] = -1; + } +} + +InputLayoutCache::~InputLayoutCache() +{ + clear(); +} + +void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context) +{ + clear(); + mDevice = device; + mDeviceContext = context; +} + +void InputLayoutCache::clear() +{ + for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) + { + SafeRelease(i->second.inputLayout); + } + mInputLayoutMap.clear(); + markDirty(); +} + +void InputLayoutCache::markDirty() +{ + mCurrentIL = NULL; + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mCurrentBuffers[i] = NULL; + mCurrentVertexStrides[i] = -1; + mCurrentVertexOffsets[i] = -1; + } +} + +GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], + gl::ProgramBinary *programBinary) +{ + int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]; + programBinary->sortAttributesByLayout(attributes, sortedSemanticIndices); + + if (!mDevice || !mDeviceContext) + { + ERR("InputLayoutCache is not initialized."); + return GL_INVALID_OPERATION; + } + + InputLayoutKey ilKey = { 0 }; + + static const char* semanticName = "TEXCOORD"; + + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (attributes[i].active) + { + D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; + + gl::VertexFormat vertexFormat(*attributes[i].attribute, attributes[i].currentValueType); + DXGI_FORMAT dxgiFormat = gl_d3d11::GetNativeVertexFormat(vertexFormat); + + // Record the type of the associated vertex shader vector in our key + // This will prevent mismatched vertex shaders from using the same input layout + GLint attributeSize; + programBinary->getActiveAttribute(sortedSemanticIndices[i], 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL); + + ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName; + ilKey.elements[ilKey.elementCount].desc.SemanticIndex = i; + ilKey.elements[ilKey.elementCount].desc.Format = dxgiFormat; + ilKey.elements[ilKey.elementCount].desc.InputSlot = i; + ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; + ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass; + ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = attributes[i].divisor; + ilKey.elementCount++; + } + } + + ID3D11InputLayout *inputLayout = NULL; + + InputLayoutMap::iterator keyIter = mInputLayoutMap.find(ilKey); + if (keyIter != mInputLayoutMap.end()) + { + inputLayout = keyIter->second.inputLayout; + keyIter->second.lastUsedTime = mCounter++; + } + else + { + gl::VertexFormat shaderInputLayout[gl::MAX_VERTEX_ATTRIBS]; + GetInputLayout(attributes, shaderInputLayout); + ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutableForInputLayout(shaderInputLayout)); + + D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS]; + for (unsigned int j = 0; j < ilKey.elementCount; ++j) + { + descs[j] = ilKey.elements[j].desc; + } + + HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout); + if (FAILED(result)) + { + ERR("Failed to crate input layout, result: 0x%08x", result); + return GL_INVALID_OPERATION; + } + + if (mInputLayoutMap.size() >= kMaxInputLayouts) + { + TRACE("Overflowed the limit of %u input layouts, removing the least recently used " + "to make room.", kMaxInputLayouts); + + InputLayoutMap::iterator leastRecentlyUsed = mInputLayoutMap.begin(); + for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) + { + if (i->second.lastUsedTime < leastRecentlyUsed->second.lastUsedTime) + { + leastRecentlyUsed = i; + } + } + SafeRelease(leastRecentlyUsed->second.inputLayout); + mInputLayoutMap.erase(leastRecentlyUsed); + } + + InputLayoutCounterPair inputCounterPair; + inputCounterPair.inputLayout = inputLayout; + inputCounterPair.lastUsedTime = mCounter++; + + mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair)); + } + + if (inputLayout != mCurrentIL) + { + mDeviceContext->IASetInputLayout(inputLayout); + mCurrentIL = inputLayout; + } + + bool dirtyBuffers = false; + size_t minDiff = gl::MAX_VERTEX_ATTRIBS; + size_t maxDiff = 0; + for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + ID3D11Buffer *buffer = NULL; + + if (attributes[i].active) + { + VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer); + Buffer11 *bufferStorage = attributes[i].storage ? Buffer11::makeBuffer11(attributes[i].storage) : NULL; + + buffer = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK) + : vertexBuffer->getBuffer(); + } + + UINT vertexStride = attributes[i].stride; + UINT vertexOffset = attributes[i].offset; + + if (buffer != mCurrentBuffers[i] || vertexStride != mCurrentVertexStrides[i] || + vertexOffset != mCurrentVertexOffsets[i]) + { + dirtyBuffers = true; + minDiff = std::min(minDiff, static_cast(i)); + maxDiff = std::max(maxDiff, static_cast(i)); + + mCurrentBuffers[i] = buffer; + mCurrentVertexStrides[i] = vertexStride; + mCurrentVertexOffsets[i] = vertexOffset; + } + } + + if (dirtyBuffers) + { + ASSERT(minDiff <= maxDiff && maxDiff < gl::MAX_VERTEX_ATTRIBS); + mDeviceContext->IASetVertexBuffers(minDiff, maxDiff - minDiff + 1, mCurrentBuffers + minDiff, + mCurrentVertexStrides + minDiff, mCurrentVertexOffsets + minDiff); + } + + return GL_NO_ERROR; +} + +std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout) +{ + static const unsigned int seed = 0xDEADBEEF; + + std::size_t hash = 0; + MurmurHash3_x86_32(inputLayout.begin(), inputLayout.end() - inputLayout.begin(), seed, &hash); + return hash; +} + +bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b) +{ + if (a.elementCount != b.elementCount) + { + return false; + } + + return std::equal(a.begin(), a.end(), b.begin()); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h new file mode 100644 index 0000000000..5d0ac60537 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h @@ -0,0 +1,95 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// InputLayoutCache.h: Defines InputLayoutCache, a class that builds and caches +// D3D11 input layouts. + +#ifndef LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ +#define LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ + +#include "libGLESv2/Constants.h" +#include "common/angleutils.h" + +namespace gl +{ +class ProgramBinary; +} + +namespace rx +{ +struct TranslatedAttribute; + +class InputLayoutCache +{ + public: + InputLayoutCache(); + virtual ~InputLayoutCache(); + + void initialize(ID3D11Device *device, ID3D11DeviceContext *context); + void clear(); + void markDirty(); + + GLenum applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], + gl::ProgramBinary *programBinary); + + private: + DISALLOW_COPY_AND_ASSIGN(InputLayoutCache); + + struct InputLayoutElement + { + D3D11_INPUT_ELEMENT_DESC desc; + GLenum glslElementType; + }; + + struct InputLayoutKey + { + unsigned int elementCount; + InputLayoutElement elements[gl::MAX_VERTEX_ATTRIBS]; + + const char *begin() const + { + return reinterpret_cast(&elementCount); + } + + const char *end() const + { + return reinterpret_cast(&elements[elementCount]); + } + }; + + struct InputLayoutCounterPair + { + ID3D11InputLayout *inputLayout; + unsigned long long lastUsedTime; + }; + + ID3D11InputLayout *mCurrentIL; + ID3D11Buffer *mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS]; + UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS]; + UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS]; + + static std::size_t hashInputLayout(const InputLayoutKey &inputLayout); + static bool compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b); + + typedef std::size_t (*InputLayoutHashFunction)(const InputLayoutKey &); + typedef bool (*InputLayoutEqualityFunction)(const InputLayoutKey &, const InputLayoutKey &); + typedef std::unordered_map InputLayoutMap; + InputLayoutMap mInputLayoutMap; + + static const unsigned int kMaxInputLayouts; + + unsigned long long mCounter; + + ID3D11Device *mDevice; + ID3D11DeviceContext *mDeviceContext; +}; + +} + +#endif // LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp new file mode 100644 index 0000000000..07040342c7 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp @@ -0,0 +1,253 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// PixelTransfer11.cpp: +// Implementation for buffer-to-texture and texture-to-buffer copies. +// Used to implement pixel transfers from unpack and to pack buffers. +// + +#include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h" +#include "libGLESv2/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/Context.h" + +// Precompiled shaders +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexturevs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexturegs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4fps.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4ips.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4uips.h" + +namespace rx +{ + +PixelTransfer11::PixelTransfer11(Renderer11 *renderer) + : mRenderer(renderer), + mBufferToTextureVS(NULL), + mBufferToTextureGS(NULL), + mParamsConstantBuffer(NULL), + mCopyRasterizerState(NULL), + mCopyDepthStencilState(NULL) +{ + HRESULT result = S_OK; + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RASTERIZER_DESC rasterDesc; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.CullMode = D3D11_CULL_NONE; + rasterDesc.FrontCounterClockwise = FALSE; + rasterDesc.DepthBias = 0; + rasterDesc.SlopeScaledDepthBias = 0.0f; + rasterDesc.DepthBiasClamp = 0.0f; + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.ScissorEnable = FALSE; + rasterDesc.MultisampleEnable = FALSE; + rasterDesc.AntialiasedLineEnable = FALSE; + + result = device->CreateRasterizerState(&rasterDesc, &mCopyRasterizerState); + ASSERT(SUCCEEDED(result)); + + D3D11_DEPTH_STENCIL_DESC depthStencilDesc; + depthStencilDesc.DepthEnable = true; + depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; + depthStencilDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.StencilEnable = FALSE; + depthStencilDesc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; + depthStencilDesc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; + depthStencilDesc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + depthStencilDesc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilDepthFailOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; + depthStencilDesc.BackFace.StencilFunc = D3D11_COMPARISON_ALWAYS; + + result = device->CreateDepthStencilState(&depthStencilDesc, &mCopyDepthStencilState); + ASSERT(SUCCEEDED(result)); + + D3D11_BUFFER_DESC constantBufferDesc = { 0 }; + constantBufferDesc.ByteWidth = rx::roundUp(sizeof(CopyShaderParams), 32u); + constantBufferDesc.Usage = D3D11_USAGE_DYNAMIC; + constantBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + constantBufferDesc.MiscFlags = 0; + constantBufferDesc.StructureByteStride = 0; + + result = device->CreateBuffer(&constantBufferDesc, NULL, &mParamsConstantBuffer); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mParamsConstantBuffer, "PixelTransfer11 constant buffer"); + + StructZero(&mParamsData); + + // init shaders + if (mRenderer->isLevel9()) + return; + + mBufferToTextureVS = d3d11::CompileVS(device, g_VS_BufferToTexture, "BufferToTexture VS"); + mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS"); + + buildShaderMap(); +} + +PixelTransfer11::~PixelTransfer11() +{ + for (auto shaderMapIt = mBufferToTexturePSMap.begin(); shaderMapIt != mBufferToTexturePSMap.end(); shaderMapIt++) + { + SafeRelease(shaderMapIt->second); + } + + mBufferToTexturePSMap.clear(); + + SafeRelease(mBufferToTextureVS); + SafeRelease(mBufferToTextureGS); + SafeRelease(mParamsConstantBuffer); + SafeRelease(mCopyRasterizerState); + SafeRelease(mCopyDepthStencilState); +} + +void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat, + const gl::PixelUnpackState &unpack, unsigned int offset, CopyShaderParams *parametersOut) +{ + StructZero(parametersOut); + + float texelCenterX = 0.5f / static_cast(destSize.width - 1); + float texelCenterY = 0.5f / static_cast(destSize.height - 1); + + unsigned int bytesPerPixel = gl::GetPixelBytes(internalFormat); + unsigned int alignmentBytes = static_cast(unpack.alignment); + unsigned int alignmentPixels = (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel); + + parametersOut->FirstPixelOffset = offset; + parametersOut->PixelsPerRow = static_cast(destArea.width); + parametersOut->RowStride = roundUp(parametersOut->PixelsPerRow, alignmentPixels); + parametersOut->RowsPerSlice = static_cast(destArea.height); + parametersOut->PositionOffset[0] = texelCenterX + (destArea.x / float(destSize.width)) * 2.0f - 1.0f; + parametersOut->PositionOffset[1] = texelCenterY + ((destSize.height - destArea.y - 1) / float(destSize.height)) * 2.0f - 1.0f; + parametersOut->PositionScale[0] = 2.0f / static_cast(destSize.width); + parametersOut->PositionScale[1] = -2.0f / static_cast(destSize.height); +} + +bool PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +{ + gl::Extents destSize = destRenderTarget->getExtents(); + + if (destArea.x < 0 || destArea.x + destArea.width > destSize.width || + destArea.y < 0 || destArea.y + destArea.height > destSize.height || + destArea.z < 0 || destArea.z + destArea.depth > destSize.depth ) + { + return false; + } + + const gl::Buffer &sourceBuffer = *unpack.pixelBuffer.get(); + + ASSERT(mRenderer->supportsFastCopyBufferToTexture(destinationFormat)); + + ID3D11PixelShader *pixelShader = findBufferToTexturePS(destinationFormat); + ASSERT(pixelShader); + + // The SRV must be in the proper read format, which may be different from the destination format + // EG: for half float data, we can load full precision floats with implicit conversion + GLenum unsizedFormat = gl::GetFormat(destinationFormat); + GLenum sourceFormat = gl::GetSizedInternalFormat(unsizedFormat, sourcePixelsType); + + DXGI_FORMAT srvFormat = gl_d3d11::GetSRVFormat(sourceFormat); + ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN); + Buffer11 *bufferStorage11 = Buffer11::makeBuffer11(sourceBuffer.getImplementation()); + ID3D11ShaderResourceView *bufferSRV = bufferStorage11->getSRV(srvFormat); + ASSERT(bufferSRV != NULL); + + ID3D11RenderTargetView *textureRTV = RenderTarget11::makeRenderTarget11(destRenderTarget)->getRenderTargetView(); + ASSERT(textureRTV != NULL); + + CopyShaderParams shaderParams; + setBufferToTextureCopyParams(destArea, destSize, sourceFormat, unpack, offset, &shaderParams); + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + ID3D11ShaderResourceView *nullSRV = NULL; + ID3D11Buffer *nullBuffer = NULL; + UINT zero = 0; + + // Are we doing a 2D or 3D copy? + ID3D11GeometryShader *geometryShader = ((destSize.depth > 1) ? mBufferToTextureGS : NULL); + + deviceContext->VSSetShader(mBufferToTextureVS, NULL, 0); + deviceContext->GSSetShader(geometryShader, NULL, 0); + deviceContext->PSSetShader(pixelShader, NULL, 0); + deviceContext->PSSetShaderResources(0, 1, &bufferSRV); + deviceContext->IASetInputLayout(NULL); + deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_POINTLIST); + + deviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); + deviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); + deviceContext->OMSetDepthStencilState(mCopyDepthStencilState, 0xFFFFFFFF); + deviceContext->RSSetState(mCopyRasterizerState); + + mRenderer->setOneTimeRenderTarget(textureRTV); + + if (!StructEquals(mParamsData, shaderParams)) + { + d3d11::SetBufferData(deviceContext, mParamsConstantBuffer, shaderParams); + mParamsData = shaderParams; + } + + deviceContext->VSSetConstantBuffers(0, 1, &mParamsConstantBuffer); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = destSize.width; + viewport.Height = destSize.height; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + UINT numPixels = (destArea.width * destArea.height * destArea.depth); + deviceContext->Draw(numPixels, 0); + + // Unbind textures and render targets and vertex buffer + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + deviceContext->VSSetConstantBuffers(0, 1, &nullBuffer); + + mRenderer->markAllStateDirty(); + + return true; +} + +void PixelTransfer11::buildShaderMap() +{ + ID3D11Device *device = mRenderer->getDevice(); + + mBufferToTexturePSMap[GL_FLOAT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4F, "BufferToTexture RGBA ps"); + mBufferToTexturePSMap[GL_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4I, "BufferToTexture RGBA-I ps"); + mBufferToTexturePSMap[GL_UNSIGNED_INT] = d3d11::CompilePS(device, g_PS_BufferToTexture_4UI, "BufferToTexture RGBA-UI ps"); +} + +ID3D11PixelShader *PixelTransfer11::findBufferToTexturePS(GLenum internalFormat) const +{ + GLenum componentType = gl::GetComponentType(internalFormat); + + if (componentType == GL_SIGNED_NORMALIZED || componentType == GL_UNSIGNED_NORMALIZED) + { + componentType = GL_FLOAT; + } + + auto shaderMapIt = mBufferToTexturePSMap.find(componentType); + return (shaderMapIt == mBufferToTexturePSMap.end() ? NULL : shaderMapIt->second); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h new file mode 100644 index 0000000000..2e2fee8f50 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h @@ -0,0 +1,82 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// PixelTransfer11.h: +// Buffer-to-Texture and Texture-to-Buffer data transfers. +// Used to implement pixel unpack and pixel pack buffers in ES3. + +#ifndef LIBGLESV2_PIXELTRANSFER11_H_ +#define LIBGLESV2_PIXELTRANSFER11_H_ + +#include "common/platform.h" + +namespace gl +{ + +class Buffer; +struct Box; +struct Extents; +struct PixelUnpackState; + +} + +namespace rx +{ +class Renderer11; +class RenderTarget; + +class PixelTransfer11 +{ + public: + explicit PixelTransfer11(Renderer11 *renderer); + ~PixelTransfer11(); + + static bool supportsBufferToTextureCopy(GLenum internalFormat); + + // unpack: the source buffer is stored in the unpack state, and buffer strides + // offset: the start of the data within the unpack buffer + // destRenderTarget: individual slice/layer of a target texture + // destinationFormat/sourcePixelsType: determines shaders + shader parameters + // destArea: the sub-section of destRenderTarget to copy to + bool copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + + private: + + struct CopyShaderParams + { + unsigned int FirstPixelOffset; + unsigned int PixelsPerRow; + unsigned int RowStride; + unsigned int RowsPerSlice; + float PositionOffset[2]; + float PositionScale[2]; + int TexLocationOffset[2]; + int TexLocationScale[2]; + }; + + static void setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat, + const gl::PixelUnpackState &unpack, unsigned int offset, CopyShaderParams *parametersOut); + + void buildShaderMap(); + ID3D11PixelShader *findBufferToTexturePS(GLenum internalFormat) const; + + Renderer11 *mRenderer; + + std::map mBufferToTexturePSMap; + ID3D11VertexShader *mBufferToTextureVS; + ID3D11GeometryShader *mBufferToTextureGS; + ID3D11Buffer *mParamsConstantBuffer; + CopyShaderParams mParamsData; + + ID3D11RasterizerState *mCopyRasterizerState; + ID3D11DepthStencilState *mCopyDepthStencilState; + +}; + +} + +#endif // LIBGLESV2_PIXELTRANSFER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp new file mode 100644 index 0000000000..17cf5cad47 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp @@ -0,0 +1,155 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl. + +#include "libGLESv2/renderer/d3d/d3d11/Query11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/main.h" + +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) +{ + mRenderer = renderer; + mQuery = NULL; +} + +Query11::~Query11() +{ + SafeRelease(mQuery); +} + +void Query11::begin() +{ + if (mQuery == NULL) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = gl_d3d11::ConvertQueryType(getType()); + queryDesc.MiscFlags = 0; + + if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + mRenderer->getDeviceContext()->Begin(mQuery); +} + +void Query11::end() +{ + ASSERT(mQuery); + mRenderer->getDeviceContext()->End(mQuery); + + mStatus = GL_FALSE; + mResult = GL_FALSE; +} + +GLuint Query11::getResult() +{ + if (mQuery != NULL) + { + while (!testQuery()) + { + Sleep(0); + // explicitly check for device loss, some drivers seem to return S_FALSE + // if the device is lost + if (mRenderer->testDeviceLost(true)) + { + return gl::error(GL_OUT_OF_MEMORY, 0); + } + } + } + + return mResult; +} + +GLboolean Query11::isResultAvailable() +{ + if (mQuery != NULL) + { + testQuery(); + } + + return mStatus; +} + +GLboolean Query11::testQuery() +{ + if (mQuery != NULL && mStatus != GL_TRUE) + { + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + bool queryFinished = false; + 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) + { + mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; + } + } + break; + + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + { + UINT64 numPrimitives = 0; + queryFinished = checkStreamOutPrimitivesWritten(context, mQuery, &numPrimitives); + if (queryFinished) + { + mResult = static_cast(numPrimitives); + } + } + break; + + default: + UNREACHABLE(); + break; + } + + if (queryFinished) + { + mStatus = GL_TRUE; + } + else if (mRenderer->testDeviceLost(true)) + { + return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); + } + + return mStatus; + } + + return GL_TRUE; // prevent blocking when query is null +} + +bool Query11::isStarted() const +{ + return (mQuery != NULL); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h new file mode 100644 index 0000000000..7a3df46d4f --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h @@ -0,0 +1,41 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Query11.h: Defines the rx::Query11 class which implements rx::QueryImpl. + +#ifndef LIBGLESV2_RENDERER_QUERY11_H_ +#define LIBGLESV2_RENDERER_QUERY11_H_ + +#include "libGLESv2/renderer/QueryImpl.h" + +namespace rx +{ +class Renderer11; + +class Query11 : public QueryImpl +{ + public: + Query11(rx::Renderer11 *renderer, GLenum type); + virtual ~Query11(); + + virtual void begin(); + virtual void end(); + virtual GLuint getResult(); + virtual GLboolean isResultAvailable(); + virtual bool isStarted() const; + + private: + DISALLOW_COPY_AND_ASSIGN(Query11); + + GLboolean testQuery(); + + rx::Renderer11 *mRenderer; + ID3D11Query *mQuery; +}; + +} + +#endif // LIBGLESV2_RENDERER_QUERY11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp new file mode 100644 index 0000000000..b185d97604 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp @@ -0,0 +1,436 @@ +#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 +// found in the LICENSE file. +// + +// RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render +// state objects. + +#include "libGLESv2/renderer/d3d/d3d11/RenderStateCache.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" + +#include "common/debug.h" +#include "third_party/murmurhash/MurmurHash3.h" + +namespace rx +{ + +template +static void ClearStateMap(mapType &map) +{ + for (typename mapType::iterator i = map.begin(); i != map.end(); i++) + { + SafeRelease(i->second.first); + } + map.clear(); +} + +// MSDN's documentation of ID3D11Device::CreateBlendState, ID3D11Device::CreateRasterizerState, +// ID3D11Device::CreateDepthStencilState and ID3D11Device::CreateSamplerState claims the maximum +// number of unique states of each type an application can create is 4096 +const unsigned int RenderStateCache::kMaxBlendStates = 4096; +const unsigned int RenderStateCache::kMaxRasterizerStates = 4096; +const unsigned int RenderStateCache::kMaxDepthStencilStates = 4096; +const unsigned int RenderStateCache::kMaxSamplerStates = 4096; + +RenderStateCache::RenderStateCache() : mDevice(NULL), mCounter(0), + mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates), + mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates), + mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates), + mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates) +{ +} + +RenderStateCache::~RenderStateCache() +{ + clear(); +} + +void RenderStateCache::initialize(ID3D11Device *device) +{ + clear(); + mDevice = device; +} + +void RenderStateCache::clear() +{ + ClearStateMap(mBlendStateCache); + ClearStateMap(mRasterizerStateCache); + ClearStateMap(mDepthStencilStateCache); + ClearStateMap(mSamplerStateCache); +} + +std::size_t RenderStateCache::hashBlendState(const BlendStateKey &blendState) +{ + static const unsigned int seed = 0xABCDEF98; + + std::size_t hash = 0; + MurmurHash3_x86_32(&blendState, sizeof(gl::BlendState), seed, &hash); + return hash; +} + +bool RenderStateCache::compareBlendStates(const BlendStateKey &a, const BlendStateKey &b) +{ + return memcmp(&a, &b, sizeof(BlendStateKey)) == 0; +} + +ID3D11BlendState *RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState) +{ + if (!mDevice) + { + ERR("RenderStateCache is not initialized."); + return NULL; + } + + bool mrt = false; + + BlendStateKey key = { 0 }; + key.blendState = blendState; + for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + { + const gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(i); + if (attachment) + { + if (i > 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; + } + } + + BlendStateMap::iterator keyIter = mBlendStateCache.find(key); + if (keyIter != mBlendStateCache.end()) + { + BlendStateCounterPair &state = keyIter->second; + state.second = mCounter++; + return state.first; + } + else + { + if (mBlendStateCache.size() >= kMaxBlendStates) + { + TRACE("Overflowed the limit of %u blend states, removing the least recently used " + "to make room.", kMaxBlendStates); + + BlendStateMap::iterator leastRecentlyUsed = mBlendStateCache.begin(); + for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) + { + leastRecentlyUsed = i; + } + } + SafeRelease(leastRecentlyUsed->second.first); + mBlendStateCache.erase(leastRecentlyUsed); + } + + // Create a new blend state and insert it into the cache + D3D11_BLEND_DESC blendDesc = { 0 }; + blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage; + blendDesc.IndependentBlendEnable = mrt ? TRUE : FALSE; + + for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) + { + D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i]; + + rtBlend.BlendEnable = blendState.blend; + if (blendState.blend) + { + rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false); + rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false); + rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB); + + rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true); + rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true); + rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha); + } + + rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(key.rtChannels[i][0] && blendState.colorMaskRed, + key.rtChannels[i][1] && blendState.colorMaskGreen, + key.rtChannels[i][2] && blendState.colorMaskBlue, + key.rtChannels[i][3] && blendState.colorMaskAlpha); + } + + ID3D11BlendState *dx11BlendState = NULL; + HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState); + if (FAILED(result) || !dx11BlendState) + { + ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); + return NULL; + } + + mBlendStateCache.insert(std::make_pair(key, std::make_pair(dx11BlendState, mCounter++))); + + return dx11BlendState; + } +} + +std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rasterState) +{ + static const unsigned int seed = 0xABCDEF98; + + std::size_t hash = 0; + MurmurHash3_x86_32(&rasterState, sizeof(RasterizerStateKey), seed, &hash); + return hash; +} + +bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b) +{ + return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0; +} + +ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, bool scissorEnabled) +{ + if (!mDevice) + { + ERR("RenderStateCache is not initialized."); + return NULL; + } + + RasterizerStateKey key = { 0 }; + key.rasterizerState = rasterState; + key.scissorEnabled = scissorEnabled; + + RasterizerStateMap::iterator keyIter = mRasterizerStateCache.find(key); + if (keyIter != mRasterizerStateCache.end()) + { + RasterizerStateCounterPair &state = keyIter->second; + state.second = mCounter++; + return state.first; + } + else + { + if (mRasterizerStateCache.size() >= kMaxRasterizerStates) + { + TRACE("Overflowed the limit of %u rasterizer states, removing the least recently used " + "to make room.", kMaxRasterizerStates); + + RasterizerStateMap::iterator leastRecentlyUsed = mRasterizerStateCache.begin(); + for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) + { + leastRecentlyUsed = i; + } + } + SafeRelease(leastRecentlyUsed->second.first); + mRasterizerStateCache.erase(leastRecentlyUsed); + } + + D3D11_CULL_MODE cullMode = gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode); + + // Disable culling if drawing points + if (rasterState.pointDrawMode) + { + cullMode = D3D11_CULL_NONE; + } + + D3D11_RASTERIZER_DESC rasterDesc; + rasterDesc.FillMode = D3D11_FILL_SOLID; + rasterDesc.CullMode = cullMode; + rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE: TRUE; + rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though. + rasterDesc.DepthClipEnable = TRUE; + rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE; + rasterDesc.MultisampleEnable = rasterState.multiSample; + rasterDesc.AntialiasedLineEnable = FALSE; + + if (rasterState.polygonOffsetFill) + { + rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor; + rasterDesc.DepthBias = (INT)rasterState.polygonOffsetUnits; + } + else + { + rasterDesc.SlopeScaledDepthBias = 0.0f; + rasterDesc.DepthBias = 0; + } + + ID3D11RasterizerState *dx11RasterizerState = NULL; + HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState); + if (FAILED(result) || !dx11RasterizerState) + { + ERR("Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result); + return NULL; + } + + mRasterizerStateCache.insert(std::make_pair(key, std::make_pair(dx11RasterizerState, mCounter++))); + + return dx11RasterizerState; + } +} + +std::size_t RenderStateCache::hashDepthStencilState(const gl::DepthStencilState &dsState) +{ + static const unsigned int seed = 0xABCDEF98; + + std::size_t hash = 0; + MurmurHash3_x86_32(&dsState, sizeof(gl::DepthStencilState), seed, &hash); + return hash; +} + +bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b) +{ + return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0; +} + +ID3D11DepthStencilState *RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState) +{ + if (!mDevice) + { + ERR("RenderStateCache is not initialized."); + return NULL; + } + + DepthStencilStateMap::iterator keyIter = mDepthStencilStateCache.find(dsState); + if (keyIter != mDepthStencilStateCache.end()) + { + DepthStencilStateCounterPair &state = keyIter->second; + state.second = mCounter++; + return state.first; + } + else + { + if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates) + { + TRACE("Overflowed the limit of %u depth stencil states, removing the least recently used " + "to make room.", kMaxDepthStencilStates); + + DepthStencilStateMap::iterator leastRecentlyUsed = mDepthStencilStateCache.begin(); + for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) + { + leastRecentlyUsed = i; + } + } + SafeRelease(leastRecentlyUsed->second.first); + mDepthStencilStateCache.erase(leastRecentlyUsed); + } + + D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 }; + dsDesc.DepthEnable = dsState.depthTest ? TRUE : FALSE; + dsDesc.DepthWriteMask = gl_d3d11::ConvertDepthMask(dsState.depthMask); + dsDesc.DepthFunc = gl_d3d11::ConvertComparison(dsState.depthFunc); + dsDesc.StencilEnable = dsState.stencilTest ? TRUE : FALSE; + dsDesc.StencilReadMask = gl_d3d11::ConvertStencilMask(dsState.stencilMask); + dsDesc.StencilWriteMask = gl_d3d11::ConvertStencilMask(dsState.stencilWritemask); + dsDesc.FrontFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilFail); + dsDesc.FrontFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthFail); + dsDesc.FrontFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthPass); + dsDesc.FrontFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilFunc); + dsDesc.BackFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackFail); + dsDesc.BackFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthFail); + dsDesc.BackFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthPass); + dsDesc.BackFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilBackFunc); + + ID3D11DepthStencilState *dx11DepthStencilState = NULL; + HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState); + if (FAILED(result) || !dx11DepthStencilState) + { + ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); + return NULL; + } + + mDepthStencilStateCache.insert(std::make_pair(dsState, std::make_pair(dx11DepthStencilState, mCounter++))); + + return dx11DepthStencilState; + } +} + +std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState) +{ + static const unsigned int seed = 0xABCDEF98; + + std::size_t hash = 0; + MurmurHash3_x86_32(&samplerState, sizeof(gl::SamplerState), seed, &hash); + return hash; +} + +bool RenderStateCache::compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b) +{ + return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0; +} + +ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &samplerState) +{ + if (!mDevice) + { + ERR("RenderStateCache is not initialized."); + return NULL; + } + + SamplerStateMap::iterator keyIter = mSamplerStateCache.find(samplerState); + if (keyIter != mSamplerStateCache.end()) + { + SamplerStateCounterPair &state = keyIter->second; + state.second = mCounter++; + return state.first; + } + else + { + if (mSamplerStateCache.size() >= kMaxSamplerStates) + { + TRACE("Overflowed the limit of %u sampler states, removing the least recently used " + "to make room.", kMaxSamplerStates); + + SamplerStateMap::iterator leastRecentlyUsed = mSamplerStateCache.begin(); + for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++) + { + if (i->second.second < leastRecentlyUsed->second.second) + { + leastRecentlyUsed = i; + } + } + SafeRelease(leastRecentlyUsed->second.first); + mSamplerStateCache.erase(leastRecentlyUsed); + } + + D3D11_SAMPLER_DESC samplerDesc; + samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter, + samplerState.maxAnisotropy, samplerState.compareMode); + samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS); + samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT); + samplerDesc.AddressW = gl_d3d11::ConvertTextureWrap(samplerState.wrapR); + samplerDesc.MipLODBias = 0; + samplerDesc.MaxAnisotropy = samplerState.maxAnisotropy; + samplerDesc.ComparisonFunc = gl_d3d11::ConvertComparison(samplerState.compareFunc); + samplerDesc.BorderColor[0] = 0.0f; + samplerDesc.BorderColor[1] = 0.0f; + samplerDesc.BorderColor[2] = 0.0f; + samplerDesc.BorderColor[3] = 0.0f; + samplerDesc.MinLOD = samplerState.minLod; + samplerDesc.MaxLOD = samplerState.maxLod; + + ID3D11SamplerState *dx11SamplerState = NULL; + HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState); + if (FAILED(result) || !dx11SamplerState) + { + ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); + return NULL; + } + + mSamplerStateCache.insert(std::make_pair(samplerState, std::make_pair(dx11SamplerState, mCounter++))); + + return dx11SamplerState; + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h new file mode 100644 index 0000000000..e6380fbd82 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h @@ -0,0 +1,109 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderStateCache.h: Defines rx::RenderStateCache, a cache of Direct3D render +// state objects. + +#ifndef LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ +#define LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ + +#include "libGLESv2/angletypes.h" +#include "common/angleutils.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer11; + +class RenderStateCache +{ + public: + RenderStateCache(); + virtual ~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); + + private: + DISALLOW_COPY_AND_ASSIGN(RenderStateCache); + + unsigned long long mCounter; + + // Blend state cache + struct BlendStateKey + { + gl::BlendState blendState; + bool rtChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; + }; + static std::size_t hashBlendState(const BlendStateKey &blendState); + static bool compareBlendStates(const BlendStateKey &a, const BlendStateKey &b); + static const unsigned int kMaxBlendStates; + + typedef std::size_t (*BlendStateHashFunction)(const BlendStateKey &); + typedef bool (*BlendStateEqualityFunction)(const BlendStateKey &, const BlendStateKey &); + typedef std::pair BlendStateCounterPair; + typedef std::unordered_map BlendStateMap; + BlendStateMap mBlendStateCache; + + // Rasterizer state cache + struct RasterizerStateKey + { + gl::RasterizerState rasterizerState; + bool scissorEnabled; + }; + static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState); + static bool compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b); + static const unsigned int kMaxRasterizerStates; + + typedef std::size_t (*RasterizerStateHashFunction)(const RasterizerStateKey &); + typedef bool (*RasterizerStateEqualityFunction)(const RasterizerStateKey &, const RasterizerStateKey &); + typedef std::pair RasterizerStateCounterPair; + typedef std::unordered_map RasterizerStateMap; + RasterizerStateMap mRasterizerStateCache; + + // Depth stencil state cache + static std::size_t hashDepthStencilState(const gl::DepthStencilState &dsState); + static bool compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b); + static const unsigned int kMaxDepthStencilStates; + + typedef std::size_t (*DepthStencilStateHashFunction)(const gl::DepthStencilState &); + typedef bool (*DepthStencilStateEqualityFunction)(const gl::DepthStencilState &, const gl::DepthStencilState &); + typedef std::pair DepthStencilStateCounterPair; + typedef std::unordered_map DepthStencilStateMap; + DepthStencilStateMap mDepthStencilStateCache; + + // Sample state cache + static std::size_t hashSamplerState(const gl::SamplerState &samplerState); + static bool compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b); + static const unsigned int kMaxSamplerStates; + + typedef std::size_t (*SamplerStateHashFunction)(const gl::SamplerState &); + typedef bool (*SamplerStateEqualityFunction)(const gl::SamplerState &, const gl::SamplerState &); + typedef std::pair SamplerStateCounterPair; + typedef std::unordered_map SamplerStateMap; + SamplerStateMap mSamplerStateCache; + + ID3D11Device *mDevice; +}; + +} + +#endif // LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp new file mode 100644 index 0000000000..6aa75ae5bd --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp @@ -0,0 +1,457 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers +// retained by Renderbuffers. + +#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" + +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +static bool getTextureProperties(ID3D11Resource *resource, unsigned int *mipLevels, unsigned int *samples) +{ + ID3D11Texture1D *texture1D = d3d11::DynamicCastComObject(resource); + if (texture1D) + { + D3D11_TEXTURE1D_DESC texDesc; + texture1D->GetDesc(&texDesc); + SafeRelease(texture1D); + + *mipLevels = texDesc.MipLevels; + *samples = 0; + + return true; + } + + ID3D11Texture2D *texture2D = d3d11::DynamicCastComObject(resource); + if (texture2D) + { + D3D11_TEXTURE2D_DESC texDesc; + texture2D->GetDesc(&texDesc); + SafeRelease(texture2D); + + *mipLevels = texDesc.MipLevels; + *samples = texDesc.SampleDesc.Count > 1 ? texDesc.SampleDesc.Count : 0; + + return true; + } + + ID3D11Texture3D *texture3D = d3d11::DynamicCastComObject(resource); + if (texture3D) + { + D3D11_TEXTURE3D_DESC texDesc; + texture3D->GetDesc(&texDesc); + SafeRelease(texture3D); + + *mipLevels = texDesc.MipLevels; + *samples = 0; + + return true; + } + + return false; +} + +static unsigned int getRTVSubresourceIndex(ID3D11Resource *resource, ID3D11RenderTargetView *view) +{ + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + view->GetDesc(&rtvDesc); + + unsigned int mipSlice = 0; + unsigned int arraySlice = 0; + + switch (rtvDesc.ViewDimension) + { + case D3D11_RTV_DIMENSION_TEXTURE1D: + mipSlice = rtvDesc.Texture1D.MipSlice; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: + mipSlice = rtvDesc.Texture1DArray.MipSlice; + arraySlice = rtvDesc.Texture1DArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2D: + mipSlice = rtvDesc.Texture2D.MipSlice; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: + mipSlice = rtvDesc.Texture2DArray.MipSlice; + arraySlice = rtvDesc.Texture2DArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMS: + mipSlice = 0; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: + mipSlice = 0; + arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice; + break; + + case D3D11_RTV_DIMENSION_TEXTURE3D: + mipSlice = rtvDesc.Texture3D.MipSlice; + arraySlice = 0; + break; + + case D3D11_RTV_DIMENSION_UNKNOWN: + case D3D11_RTV_DIMENSION_BUFFER: + UNIMPLEMENTED(); + break; + + default: + UNREACHABLE(); + break; + } + + unsigned int mipLevels, samples; + getTextureProperties(resource, &mipLevels, &samples); + + return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); +} + +static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11DepthStencilView *view) +{ + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + view->GetDesc(&dsvDesc); + + unsigned int mipSlice = 0; + unsigned int arraySlice = 0; + + switch (dsvDesc.ViewDimension) + { + case D3D11_DSV_DIMENSION_TEXTURE1D: + mipSlice = dsvDesc.Texture1D.MipSlice; + arraySlice = 0; + break; + + case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: + mipSlice = dsvDesc.Texture1DArray.MipSlice; + arraySlice = dsvDesc.Texture1DArray.FirstArraySlice; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2D: + mipSlice = dsvDesc.Texture2D.MipSlice; + arraySlice = 0; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: + mipSlice = dsvDesc.Texture2DArray.MipSlice; + arraySlice = dsvDesc.Texture2DArray.FirstArraySlice; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMS: + mipSlice = 0; + arraySlice = 0; + break; + + case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: + mipSlice = 0; + arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice; + break; + + case D3D11_DSV_DIMENSION_UNKNOWN: + UNIMPLEMENTED(); + break; + + default: + UNREACHABLE(); + break; + } + + unsigned int mipLevels, samples; + getTextureProperties(resource, &mipLevels, &samples); + + return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); +} + +RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Resource *resource, + ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth) +{ + mRenderer = Renderer11::makeRenderer11(renderer); + + mTexture = resource; + if (mTexture) + { + mTexture->AddRef(); + } + + mRenderTarget = rtv; + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + + mDepthStencil = NULL; + + mShaderResource = srv; + if (mShaderResource) + { + mShaderResource->AddRef(); + } + + mSubresourceIndex = 0; + + if (mRenderTarget && mTexture) + { + D3D11_RENDER_TARGET_VIEW_DESC desc; + mRenderTarget->GetDesc(&desc); + + unsigned int mipLevels, samples; + getTextureProperties(mTexture, &mipLevels, &samples); + + mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget); + mWidth = width; + mHeight = height; + mDepth = depth; + mSamples = samples; + + mInternalFormat = d3d11_gl::GetInternalFormat(desc.Format); + mActualFormat = d3d11_gl::GetInternalFormat(desc.Format); + } +} + +RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Resource *resource, + ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth) +{ + mRenderer = Renderer11::makeRenderer11(renderer); + + mTexture = resource; + if (mTexture) + { + mTexture->AddRef(); + } + + mRenderTarget = NULL; + + mDepthStencil = dsv; + if (mDepthStencil) + { + mDepthStencil->AddRef(); + } + + mShaderResource = srv; + if (mShaderResource) + { + mShaderResource->AddRef(); + } + + mSubresourceIndex = 0; + + if (mDepthStencil && mTexture) + { + D3D11_DEPTH_STENCIL_VIEW_DESC desc; + mDepthStencil->GetDesc(&desc); + + unsigned int mipLevels, samples; + getTextureProperties(mTexture, &mipLevels, &samples); + + mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil); + mWidth = width; + mHeight = height; + mDepth = depth; + mSamples = samples; + + mInternalFormat = d3d11_gl::GetInternalFormat(desc.Format); + mActualFormat = d3d11_gl::GetInternalFormat(desc.Format); + } +} + +RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples) +{ + mRenderer = Renderer11::makeRenderer11(renderer); + mTexture = NULL; + mRenderTarget = NULL; + 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); + + 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; + } + + if (width > 0 && height > 0) + { + // Create texture resource + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = texFormat; + desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + // If a rendertarget or depthstencil format exists for this texture format, + // we'll flag it to allow binding that way. Shader resource views are a little + // more complicated. + bool bindRTV = false, bindDSV = false, bindSRV = false; + bindRTV = (rtvFormat != DXGI_FORMAT_UNKNOWN); + bindDSV = (dsvFormat != DXGI_FORMAT_UNKNOWN); + if (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); + } + + desc.BindFlags = (bindRTV ? D3D11_BIND_RENDER_TARGET : 0) | + (bindDSV ? D3D11_BIND_DEPTH_STENCIL : 0) | + (bindSRV ? D3D11_BIND_SHADER_RESOURCE : 0); + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11Texture2D *texture = NULL; + HRESULT result = device->CreateTexture2D(&desc, NULL, &texture); + mTexture = texture; + + if (result == E_OUTOFMEMORY) + { + gl::error(GL_OUT_OF_MEMORY); + return; + } + ASSERT(SUCCEEDED(result)); + + if (bindSRV) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = srvFormat; + srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; + srvDesc.Texture2D.MostDetailedMip = 0; + srvDesc.Texture2D.MipLevels = 1; + result = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource); + + if (result == E_OUTOFMEMORY) + { + SafeRelease(mTexture); + gl::error(GL_OUT_OF_MEMORY); + return; + } + ASSERT(SUCCEEDED(result)); + } + + if (bindDSV) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = dsvFormat; + dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; + dsvDesc.Texture2D.MipSlice = 0; + dsvDesc.Flags = 0; + result = device->CreateDepthStencilView(mTexture, &dsvDesc, &mDepthStencil); + + if (result == E_OUTOFMEMORY) + { + SafeRelease(mTexture); + SafeRelease(mShaderResource); + gl::error(GL_OUT_OF_MEMORY); + return; + } + ASSERT(SUCCEEDED(result)); + } + + if (bindRTV) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = rtvFormat; + rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; + rtvDesc.Texture2D.MipSlice = 0; + result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget); + + if (result == E_OUTOFMEMORY) + { + SafeRelease(mTexture); + SafeRelease(mShaderResource); + SafeRelease(mDepthStencil); + gl::error(GL_OUT_OF_MEMORY); + return; + } + ASSERT(SUCCEEDED(result)); + + if (gl_d3d11::RequiresTextureDataInitialization(internalFormat)) + { + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + const float clearValues[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; + context->ClearRenderTargetView(mRenderTarget, clearValues); + } + } + } + + mWidth = width; + mHeight = height; + mDepth = 1; + mInternalFormat = internalFormat; + mSamples = supportedSamples; + mActualFormat = d3d11_gl::GetInternalFormat(texFormat); + mSubresourceIndex = D3D11CalcSubresource(0, 0, 1); +} + +RenderTarget11::~RenderTarget11() +{ + SafeRelease(mTexture); + SafeRelease(mRenderTarget); + SafeRelease(mDepthStencil); + SafeRelease(mShaderResource); +} + +RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget11*, target)); + return static_cast(target); +} + +void RenderTarget11::invalidate(GLint x, GLint y, GLsizei width, GLsizei height) +{ + // Currently a no-op +} + +ID3D11Resource *RenderTarget11::getTexture() const +{ + return mTexture; +} + +ID3D11RenderTargetView *RenderTarget11::getRenderTargetView() const +{ + return mRenderTarget; +} + +ID3D11DepthStencilView *RenderTarget11::getDepthStencilView() const +{ + return mDepthStencil; +} + +ID3D11ShaderResourceView *RenderTarget11::getShaderResourceView() const +{ + return mShaderResource; +} + +unsigned int RenderTarget11::getSubresourceIndex() const +{ + return mSubresourceIndex; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h new file mode 100644 index 0000000000..ba9f76e5de --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h @@ -0,0 +1,54 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderTarget11.h: Defines a DX11-specific wrapper for ID3D11View pointers +// retained by Renderbuffers. + +#ifndef LIBGLESV2_RENDERER_RENDERTARGET11_H_ +#define LIBGLESV2_RENDERER_RENDERTARGET11_H_ + +#include "libGLESv2/renderer/RenderTarget.h" + +namespace rx +{ +class Renderer; +class Renderer11; + +class RenderTarget11 : public RenderTarget +{ + public: + // RenderTarget11 takes ownership of any D3D11 resources it is given and will AddRef them + RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth); + RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height, GLsizei depth); + RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples); + virtual ~RenderTarget11(); + + static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget); + + virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height); + + ID3D11Resource *getTexture() const; + ID3D11RenderTargetView *getRenderTargetView() const; + ID3D11DepthStencilView *getDepthStencilView() const; + ID3D11ShaderResourceView *getShaderResourceView() const; + + unsigned int getSubresourceIndex() const; + + private: + DISALLOW_COPY_AND_ASSIGN(RenderTarget11); + + unsigned int mSubresourceIndex; + ID3D11Resource *mTexture; + ID3D11RenderTargetView *mRenderTarget; + ID3D11DepthStencilView *mDepthStencil; + ID3D11ShaderResourceView *mShaderResource; + + Renderer11 *mRenderer; +}; + +} + +#endif LIBGLESV2_RENDERER_RENDERTARGET11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp new file mode 100644 index 0000000000..17a13f97d6 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp @@ -0,0 +1,3527 @@ +#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 +// found in the LICENSE file. +// + +// 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/Buffer.h" +#include "libGLESv2/FramebufferAttachment.h" +#include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/Framebuffer.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/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" +#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" +#include "libGLESv2/renderer/d3d/d3d11/Image11.h" +#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h" +#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" +#include "libGLESv2/renderer/d3d/VertexDataManager.h" +#include "libGLESv2/renderer/d3d/IndexDataManager.h" +#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" +#include "libGLESv2/renderer/d3d/d3d11/Query11.h" +#include "libGLESv2/renderer/d3d/d3d11/Fence11.h" +#include "libGLESv2/renderer/d3d/d3d11/Blit11.h" +#include "libGLESv2/renderer/d3d/d3d11/Clear11.h" +#include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h" +#include "libGLESv2/renderer/d3d/d3d11/VertexArray11.h" +#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h" +#include "libEGL/Display.h" + +// Enable ANGLE_SKIP_DXGI_1_2_CHECK if there is not a possibility of using cross-process +// HWNDs or the Windows 7 Platform Update (KB2670838) is expected to be installed. +#ifndef ANGLE_SKIP_DXGI_1_2_CHECK +#define ANGLE_SKIP_DXGI_1_2_CHECK 0 +#endif + +#ifdef _DEBUG +// this flag enables suppressing some spurious warnings that pop up in certain WebGL samples +// and conformance tests. to enable all warnings, remove this define. +#define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1 +#endif + +namespace rx +{ +static const DXGI_FORMAT RenderTargetFormats[] = + { + DXGI_FORMAT_B8G8R8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM + }; + +static const DXGI_FORMAT DepthStencilFormats[] = + { + DXGI_FORMAT_UNKNOWN, + DXGI_FORMAT_D24_UNORM_S8_UINT, + DXGI_FORMAT_D16_UNORM + }; + +enum +{ + MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 +}; + +Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay) + : Renderer(display), + mDc(hDc), + mRequestedDisplay(requestedDisplay) +{ + mVertexDataManager = NULL; + mIndexDataManager = NULL; + + mLineLoopIB = NULL; + mTriangleFanIB = NULL; + + mBlit = NULL; + mPixelTransfer = NULL; + + mClear = NULL; + + mSyncQuery = NULL; + + mD3d11Module = NULL; + mDxgiModule = NULL; + + mDeviceLost = false; + + mMaxSupportedSamples = 0; + + mDevice = NULL; + mDeviceContext = NULL; + mDxgiAdapter = NULL; + mDxgiFactory = NULL; + + mDriverConstantBufferVS = NULL; + mDriverConstantBufferPS = NULL; + + mAppliedVertexShader = NULL; + mAppliedGeometryShader = NULL; + mCurPointGeometryShader = NULL; + mAppliedPixelShader = NULL; +} + +Renderer11::~Renderer11() +{ + release(); +} + +Renderer11 *Renderer11::makeRenderer11(Renderer *renderer) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer11*, renderer)); + return static_cast(renderer); +} + +#ifndef __d3d11_1_h__ +#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081) +#endif + +EGLint Renderer11::initialize() +{ + if (!mCompiler.initialize()) + { + return EGL_NOT_INITIALIZED; + } + +#if !defined(ANGLE_PLATFORM_WINRT) + mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); + mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); + + if (mD3d11Module == NULL || mDxgiModule == NULL) + { + ERR("Could not load D3D11 or DXGI library - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + // create the D3D11 device + ASSERT(mDevice == NULL); + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); + + if (D3D11CreateDevice == NULL) + { + ERR("Could not retrieve D3D11CreateDevice address - aborting!\n"); + return EGL_NOT_INITIALIZED; + } +#endif + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, +#if !defined(ANGLE_ENABLE_D3D9) + D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, + D3D_FEATURE_LEVEL_9_1, +#endif + }; + + D3D_DRIVER_TYPE driverType = D3D_DRIVER_TYPE_HARDWARE; + if (mRequestedDisplay == EGL_PLATFORM_ANGLE_TYPE_D3D11_WARP_ANGLE) + { + driverType = D3D_DRIVER_TYPE_WARP; + } + + HRESULT result = S_OK; + +#ifdef _DEBUG + result = D3D11CreateDevice(NULL, + driverType, + NULL, + D3D11_CREATE_DEVICE_DEBUG, + featureLevels, + ArraySize(featureLevels), + D3D11_SDK_VERSION, + &mDevice, + &mFeatureLevel, + &mDeviceContext); + + if (!mDevice || FAILED(result)) + { + ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); + } + + if (!mDevice || FAILED(result)) +#endif + { + result = D3D11CreateDevice(NULL, + driverType, + NULL, + 0, + featureLevels, + ArraySize(featureLevels), + D3D11_SDK_VERSION, + &mDevice, + &mFeatureLevel, + &mDeviceContext); + + if (!mDevice || FAILED(result)) + { + ERR("Could not create D3D11 device - aborting!\n"); + return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer + } + } + +#if !ANGLE_SKIP_DXGI_1_2_CHECK && !defined(ANGLE_PLATFORM_WINRT) + // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required. + // The easiest way to check is to query for a IDXGIDevice2. + bool requireDXGI1_2 = false; + HWND hwnd = WindowFromDC(mDc); + if (hwnd) + { + DWORD currentProcessId = GetCurrentProcessId(); + DWORD wndProcessId; + GetWindowThreadProcessId(hwnd, &wndProcessId); + requireDXGI1_2 = (currentProcessId != wndProcessId); + } + else + { + requireDXGI1_2 = true; + } + + if (requireDXGI1_2) + { + IDXGIDevice2 *dxgiDevice2 = NULL; + result = mDevice->QueryInterface(__uuidof(IDXGIDevice2), (void**)&dxgiDevice2); + if (FAILED(result)) + { + ERR("DXGI 1.2 required to present to HWNDs owned by another process.\n"); + return EGL_NOT_INITIALIZED; + } + SafeRelease(dxgiDevice2); + } +#endif + +#if !defined(ANGLE_PLATFORM_WINRT) + IDXGIDevice *dxgiDevice = NULL; +#else + IDXGIDevice1 *dxgiDevice = NULL; +#endif + result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice)); + + if (FAILED(result)) + { + ERR("Could not query DXGI device - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter); + + if (FAILED(result)) + { + ERR("Could not retrieve DXGI adapter - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + SafeRelease(dxgiDevice); + + mDxgiAdapter->GetDesc(&mAdapterDescription); + memset(mDescription, 0, sizeof(mDescription)); + wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1); + + result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory); + + if (!mDxgiFactory || FAILED(result)) + { + ERR("Could not create DXGI factory - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log +#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) + ID3D11InfoQueue *infoQueue; + result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue); + + if (SUCCEEDED(result)) + { + D3D11_MESSAGE_ID hideMessages[] = + { + D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET + }; + + D3D11_INFO_QUEUE_FILTER filter = {0}; + filter.DenyList.NumIDs = ArraySize(hideMessages); + filter.DenyList.pIDList = hideMessages; + + infoQueue->AddStorageFilterEntries(&filter); + SafeRelease(infoQueue); + } +#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); + } + + initializeDevice(); + + return EGL_SUCCESS; +} + +// do any one-time device initialization +// NOTE: this is also needed after a device lost/reset +// to reset the scene status and ensure the default states are reset. +void Renderer11::initializeDevice() +{ + mStateCache.initialize(mDevice); + mInputLayoutCache.initialize(mDevice, mDeviceContext); + + ASSERT(!mVertexDataManager && !mIndexDataManager); + mVertexDataManager = new VertexDataManager(this); + mIndexDataManager = new IndexDataManager(this); + + ASSERT(!mBlit); + mBlit = new Blit11(this); + + ASSERT(!mClear); + mClear = new Clear11(this); + + ASSERT(!mPixelTransfer); + mPixelTransfer = new PixelTransfer11(this); + + markAllStateDirty(); +} + +int Renderer11::generateConfigs(ConfigDesc **configDescList) +{ + unsigned int numRenderFormats = ArraySize(RenderTargetFormats); + unsigned int numDepthFormats = ArraySize(DepthStencilFormats); + (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; + int numConfigs = 0; + + for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) + { + for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) + { + DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex]; + + UINT formatSupport = 0; + HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport); + + if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) + { + DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; + + bool depthStencilFormatOK = true; + + if (depthStencilFormat != DXGI_FORMAT_UNKNOWN) + { + UINT depthStencilSupport = 0; + result = mDevice->CheckFormatSupport(depthStencilFormat, &depthStencilSupport); + depthStencilFormatOK = SUCCEEDED(result) && (depthStencilSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL); + } + + if (depthStencilFormatOK) + { + ConfigDesc newConfig; + newConfig.renderTargetFormat = d3d11_gl::GetInternalFormat(renderTargetFormat); + newConfig.depthStencilFormat = d3d11_gl::GetInternalFormat(depthStencilFormat); + newConfig.multiSample = 0; // FIXME: enumerate multi-sampling + newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast + newConfig.es3Capable = true; + + (*configDescList)[numConfigs++] = newConfig; + } + } + } + } + + return numConfigs; +} + +void Renderer11::deleteConfigs(ConfigDesc *configDescList) +{ + delete [] (configDescList); +} + +void Renderer11::sync(bool block) +{ + if (block) + { + HRESULT result; + + if (!mSyncQuery) + { + D3D11_QUERY_DESC queryDesc; + queryDesc.Query = D3D11_QUERY_EVENT; + queryDesc.MiscFlags = 0; + + result = mDevice->CreateQuery(&queryDesc, &mSyncQuery); + ASSERT(SUCCEEDED(result)); + } + + mDeviceContext->End(mSyncQuery); + mDeviceContext->Flush(); + + do + { + result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); + + // Keep polling, but allow other threads to do something useful first + Sleep(0); + + if (testDeviceLost(true)) + { + return; + } + } + while (result == S_FALSE); + } + else + { + mDeviceContext->Flush(); + } +} + +SwapChain *Renderer11::createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +{ + return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat); +} + +void Renderer11::generateSwizzle(gl::Texture *texture) +{ + if (texture) + { + TextureStorageInterface *texStorage = texture->getNativeTexture(); + if (texStorage) + { + TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance()); + + storage11->generateSwizzles(texture->getSamplerState().swizzleRed, + texture->getSamplerState().swizzleGreen, + texture->getSamplerState().swizzleBlue, + texture->getSamplerState().swizzleAlpha); + } + } +} + +void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) +{ + if (type == gl::SAMPLER_PIXEL) + { + if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS) + { + ERR("Pixel shader sampler index %i is not valid.", index); + return; + } + + if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) + { + ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState); + + if (!dxSamplerState) + { + ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default" + "sampler state for pixel shaders at slot %i.", index); + } + + mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState); + + mCurPixelSamplerStates[index] = samplerState; + } + + mForceSetPixelSamplerStates[index] = false; + } + else if (type == gl::SAMPLER_VERTEX) + { + if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) + { + ERR("Vertex shader sampler index %i is not valid.", index); + return; + } + + if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) + { + ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState); + + if (!dxSamplerState) + { + ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default" + "sampler state for vertex shaders at slot %i.", index); + } + + mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState); + + mCurVertexSamplerStates[index] = samplerState; + } + + mForceSetVertexSamplerStates[index] = false; + } + else UNREACHABLE(); +} + +void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture) +{ + ID3D11ShaderResourceView *textureSRV = NULL; + 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); + } + + // 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(); + } + + if (type == gl::SAMPLER_PIXEL) + { + if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS) + { + ERR("Pixel shader sampler index %i is not valid.", index); + return; + } + + if (forceSetTexture || mCurPixelSRVs[index] != textureSRV) + { + mDeviceContext->PSSetShaderResources(index, 1, &textureSRV); + } + + mCurPixelSRVs[index] = textureSRV; + } + else if (type == gl::SAMPLER_VERTEX) + { + if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) + { + ERR("Vertex shader sampler index %i is not valid.", index); + return; + } + + if (forceSetTexture || mCurVertexSRVs[index] != textureSRV) + { + mDeviceContext->VSSetShaderResources(index, 1, &textureSRV); + } + + mCurVertexSRVs[index] = textureSRV; + } + else UNREACHABLE(); +} + +bool Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) +{ + for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++) + { + const gl::Buffer *uniformBuffer = vertexUniformBuffers[uniformBufferIndex]; + if (uniformBuffer) + { + Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation()); + ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); + + if (!constantBuffer) + { + return false; + } + + if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial()) + { + mDeviceContext->VSSetConstantBuffers(getReservedVertexUniformBuffers() + uniformBufferIndex, + 1, &constantBuffer); + mCurrentConstantBufferVS[uniformBufferIndex] = bufferStorage->getSerial(); + } + } + } + + for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++) + { + const gl::Buffer *uniformBuffer = fragmentUniformBuffers[uniformBufferIndex]; + if (uniformBuffer) + { + Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation()); + ID3D11Buffer *constantBuffer = bufferStorage->getBuffer(BUFFER_USAGE_UNIFORM); + + if (!constantBuffer) + { + return false; + } + + if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial()) + { + mDeviceContext->PSSetConstantBuffers(getReservedFragmentUniformBuffers() + uniformBufferIndex, + 1, &constantBuffer); + mCurrentConstantBufferPS[uniformBufferIndex] = bufferStorage->getSerial(); + } + } + } + + return true; +} + +void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) +{ + if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0) + { + ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled); + if (!dxRasterState) + { + ERR("NULL rasterizer state returned by RenderStateCache::getRasterizerState, setting the default" + "rasterizer state."); + } + + mDeviceContext->RSSetState(dxRasterState); + + mCurRasterState = rasterState; + } + + mForceSetRasterState = false; +} + +void Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::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) + { + ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default " + "blend state."); + } + + float blendColors[4] = {0.0f}; + if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && + blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) + { + blendColors[0] = blendColor.red; + blendColors[1] = blendColor.green; + blendColors[2] = blendColor.blue; + blendColors[3] = blendColor.alpha; + } + else + { + blendColors[0] = blendColor.alpha; + blendColors[1] = blendColor.alpha; + blendColors[2] = blendColor.alpha; + blendColors[3] = blendColor.alpha; + } + + mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask); + + mCurBlendState = blendState; + mCurBlendColor = blendColor; + mCurSampleMask = sampleMask; + } + + mForceSetBlendState = false; +} + +void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW) +{ + if (mForceSetDepthStencilState || + memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 || + stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef) + { + ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask); + ASSERT(stencilRef == stencilBackRef); + ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask); + + ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState); + if (!dxDepthStencilState) + { + ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, " + "setting the default depth stencil state."); + } + + // Max D3D11 stencil reference value is 0xFF, corresponding to the max 8 bits in a stencil buffer + // GL specifies we should clamp the ref value to the nearest bit depth when doing stencil ops + META_ASSERT(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF); + META_ASSERT(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF); + UINT dxStencilRef = std::min(stencilRef, 0xFFu); + + mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef); + + mCurDepthStencilState = depthStencilState; + mCurStencilRef = stencilRef; + mCurStencilBackRef = stencilBackRef; + } + + mForceSetDepthStencilState = false; +} + +void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) +{ + if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || + enabled != mScissorEnabled) + { + if (enabled) + { + D3D11_RECT rect; + rect.left = std::max(0, scissor.x); + rect.top = std::max(0, scissor.y); + rect.right = scissor.x + std::max(0, scissor.width); + rect.bottom = scissor.y + std::max(0, scissor.height); + + mDeviceContext->RSSetScissorRects(1, &rect); + } + + if (enabled != mScissorEnabled) + { + mForceSetRasterState = true; + } + + mCurScissor = scissor; + mScissorEnabled = enabled; + } + + mForceSetScissor = false; +} + +bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport) +{ + gl::Rectangle actualViewport = viewport; + float actualZNear = gl::clamp01(zNear); + float actualZFar = gl::clamp01(zFar); + if (ignoreViewport) + { + actualViewport.x = 0; + actualViewport.y = 0; + actualViewport.width = mRenderTargetDesc.width; + actualViewport.height = mRenderTargetDesc.height; + actualZNear = 0.0f; + actualZFar = 1.0f; + } + + const gl::Caps& caps = getRendererCaps(); + + // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds + D3D11_VIEWPORT dxViewport; + dxViewport.TopLeftX = gl::clamp(actualViewport.x, -static_cast(caps.maxViewportWidth), static_cast(caps.maxViewportWidth)); + dxViewport.TopLeftY = gl::clamp(actualViewport.y, -static_cast(caps.maxViewportHeight), static_cast(caps.maxViewportHeight)); + dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast(caps.maxViewportWidth - dxViewport.TopLeftX)); + dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast(caps.maxViewportHeight - dxViewport.TopLeftY)); + dxViewport.MinDepth = actualZNear; + dxViewport.MaxDepth = actualZFar; + + if (dxViewport.Width <= 0 || dxViewport.Height <= 0) + { + return false; // Nothing to render + } + + bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || + actualZNear != mCurNear || actualZFar != mCurFar; + + if (viewportChanged) + { + mDeviceContext->RSSetViewports(1, &dxViewport); + + mCurViewport = actualViewport; + mCurNear = actualZNear; + mCurFar = actualZFar; + + mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f; + mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f; + mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); + mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); + + mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f; + mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f; + + mVertexConstants.depthRange[0] = actualZNear; + mVertexConstants.depthRange[1] = actualZFar; + mVertexConstants.depthRange[2] = actualZFar - actualZNear; + + mPixelConstants.depthRange[0] = actualZNear; + mPixelConstants.depthRange[1] = actualZFar; + mPixelConstants.depthRange[2] = actualZFar - actualZNear; + } + + mForceSetViewport = false; + return true; +} + +bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) +{ + D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; + + GLsizei minCount = 0; + + switch (mode) + { + case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break; + case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break; + case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; + case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; + case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; + case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break; + // emulate fans via rewriting index buffer + case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; + default: + UNREACHABLE(); + return false; + } + + if (primitiveTopology != mCurrentPrimitiveTopology) + { + mDeviceContext->IASetPrimitiveTopology(primitiveTopology); + mCurrentPrimitiveTopology = primitiveTopology; + } + + return count >= minCount; +} + +bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) +{ + // Get the color render buffer and serial + // Also extract the render target dimensions and view + unsigned int renderTargetWidth = 0; + unsigned int renderTargetHeight = 0; + GLenum renderTargetFormat = 0; + unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0}; + ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; + bool missingColorRenderTarget = true; + + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + const GLenum drawBufferState = framebuffer->getDrawBufferState(colorAttachment); + gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(colorAttachment); + + if (colorbuffer && drawBufferState != GL_NONE) + { + // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order) + ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment)); + + // check for zero-sized default framebuffer, which is a special case. + // in this case we do not wish to modify any state and just silently return false. + // this will not report any gl error but will cause the calling method to return. + if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) + { + return false; + } + + renderTargetSerials[colorAttachment] = colorbuffer->getSerial(); + + // Extract the render target dimensions and view + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + if (!renderTarget) + { + ERR("render target pointer unexpectedly null."); + return false; + } + + framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); + if (!framebufferRTVs[colorAttachment]) + { + ERR("render target view pointer unexpectedly null."); + return false; + } + + if (missingColorRenderTarget) + { + renderTargetWidth = colorbuffer->getWidth(); + renderTargetHeight = colorbuffer->getHeight(); + renderTargetFormat = colorbuffer->getActualFormat(); + missingColorRenderTarget = false; + } + + // TODO: Detect if this color buffer is already bound as a texture and unbind it first to prevent + // D3D11 warnings. + } + } + + // Get the depth stencil render buffer and serials + gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer(); + unsigned int depthbufferSerial = 0; + unsigned int stencilbufferSerial = 0; + if (depthStencil) + { + depthbufferSerial = depthStencil->getSerial(); + } + else if (framebuffer->getStencilbuffer()) + { + depthStencil = framebuffer->getStencilbuffer(); + stencilbufferSerial = depthStencil->getSerial(); + } + + ID3D11DepthStencilView* framebufferDSV = NULL; + if (depthStencil) + { + RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil()); + if (!depthStencilRenderTarget) + { + ERR("render target pointer unexpectedly null."); + SafeRelease(framebufferRTVs); + return false; + } + + framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); + if (!framebufferDSV) + { + ERR("depth stencil view pointer unexpectedly null."); + SafeRelease(framebufferRTVs); + return false; + } + + // If there is no render buffer, the width, height and format values come from + // the depth stencil + if (missingColorRenderTarget) + { + renderTargetWidth = depthStencil->getWidth(); + renderTargetHeight = depthStencil->getHeight(); + renderTargetFormat = depthStencil->getActualFormat(); + } + } + + // Apply the render target and depth stencil + if (!mRenderTargetDescInitialized || !mDepthStencilInitialized || + memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 || + depthbufferSerial != mAppliedDepthbufferSerial || + stencilbufferSerial != mAppliedStencilbufferSerial) + { + mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV); + + mRenderTargetDesc.width = renderTargetWidth; + mRenderTargetDesc.height = renderTargetHeight; + mRenderTargetDesc.format = renderTargetFormat; + mForceSetViewport = true; + mForceSetScissor = true; + mForceSetBlendState = true; + + if (!mDepthStencilInitialized) + { + mForceSetRasterState = true; + } + + for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) + { + mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex]; + } + mAppliedDepthbufferSerial = depthbufferSerial; + mAppliedStencilbufferSerial = stencilbufferSerial; + mRenderTargetDescInitialized = true; + mDepthStencilInitialized = true; + } + + invalidateFramebufferSwizzles(framebuffer); + + return true; +} + +GLenum 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) + { + return err; + } + + return mInputLayoutCache.applyVertexBuffers(attributes, programBinary); +} + +GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) +{ + GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); + + if (err == GL_NO_ERROR) + { + IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); + + ID3D11Buffer *buffer = NULL; + DXGI_FORMAT bufferFormat = indexBuffer->getIndexFormat(); + + if (indexInfo->storage) + { + Buffer11 *storage = Buffer11::makeBuffer11(indexInfo->storage); + buffer = storage->getBuffer(BUFFER_USAGE_INDEX); + } + else + { + buffer = indexBuffer->getBuffer(); + } + + if (buffer != mAppliedIB || bufferFormat != mAppliedIBFormat || indexInfo->startOffset != mAppliedIBOffset) + { + mDeviceContext->IASetIndexBuffer(buffer, bufferFormat, indexInfo->startOffset); + + mAppliedIB = buffer; + mAppliedIBFormat = bufferFormat; + mAppliedIBOffset = indexInfo->startOffset; + } + } + + return err; +} + +void Renderer11::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) +{ + ID3D11Buffer* d3dBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; + UINT d3dOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; + bool requiresUpdate = false; + for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + { + if (transformFeedbackBuffers[i]) + { + Buffer11 *storage = Buffer11::makeBuffer11(transformFeedbackBuffers[i]->getImplementation()); + ID3D11Buffer *buffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK); + + d3dBuffers[i] = buffer; + d3dOffsets[i] = (mAppliedTFBuffers[i] != buffer) ? static_cast(offsets[i]) : -1; + } + else + { + d3dBuffers[i] = NULL; + d3dOffsets[i] = 0; + } + + if (d3dBuffers[i] != mAppliedTFBuffers[i] || offsets[i] != mAppliedTFOffsets[i]) + { + requiresUpdate = true; + } + } + + if (requiresUpdate) + { + mDeviceContext->SOSetTargets(ArraySize(d3dBuffers), d3dBuffers, d3dOffsets); + for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + { + mAppliedTFBuffers[i] = d3dBuffers[i]; + mAppliedTFOffsets[i] = offsets[i]; + } + } +} + +void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) +{ + if (mode == GL_POINTS && transformFeedbackActive) + { + // Since point sprites are generated with a geometry shader, too many vertices will + // be written if transform feedback is active. To work around this, draw only the points + // with the stream out shader and no pixel shader to feed the stream out buffers and then + // draw again with the point sprite geometry shader to rasterize the point sprites. + + mDeviceContext->PSSetShader(NULL, NULL, 0); + + if (instances > 0) + { + mDeviceContext->DrawInstanced(count, instances, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } + + mDeviceContext->GSSetShader(mCurPointGeometryShader, NULL, 0); + mDeviceContext->PSSetShader(mAppliedPixelShader, NULL, 0); + + if (instances > 0) + { + mDeviceContext->DrawInstanced(count, instances, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } + + mDeviceContext->GSSetShader(mAppliedGeometryShader, NULL, 0); + } + else if (mode == GL_LINE_LOOP) + { + drawLineLoop(count, GL_NONE, NULL, 0, NULL); + } + else if (mode == GL_TRIANGLE_FAN) + { + drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances); + } + else if (instances > 0) + { + mDeviceContext->DrawInstanced(count, instances, 0, 0); + } + else + { + mDeviceContext->Draw(count, 0); + } +} + +void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, + gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) +{ + if (mode == GL_LINE_LOOP) + { + drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); + } + else if (mode == GL_TRIANGLE_FAN) + { + drawTriangleFan(count, type, indices, indexInfo.minIndex, elementArrayBuffer, instances); + } + else if (instances > 0) + { + mDeviceContext->DrawIndexedInstanced(count, instances, 0, -static_cast(indexInfo.minIndex), 0); + } + else + { + mDeviceContext->DrawIndexed(count, 0, -static_cast(indexInfo.minIndex)); + } +} + +template +static void fillLineLoopIndices(GLenum type, GLsizei count, const GLvoid *indices, T *data) +{ + switch (type) + { + case GL_NONE: // Non-indexed draw + for (int i = 0; i < count; i++) + { + data[i] = i; + } + data[count] = 0; + break; + case GL_UNSIGNED_BYTE: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_SHORT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_INT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + default: UNREACHABLE(); + } +} + +template +static void fillTriangleFanIndices(GLenum type, unsigned int numTris, const GLvoid *indices, T *data) +{ + switch (type) + { + case GL_NONE: // Non-indexed draw + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = 0; + data[i*3 + 1] = i + 1; + data[i*3 + 2] = i + 2; + } + break; + case GL_UNSIGNED_BYTE: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + case GL_UNSIGNED_SHORT: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + case GL_UNSIGNED_INT: + for (unsigned int i = 0; i < numTris; i++) + { + data[i*3 + 0] = static_cast(indices)[0]; + data[i*3 + 1] = static_cast(indices)[i + 1]; + data[i*3 + 2] = static_cast(indices)[i + 2]; + } + break; + default: UNREACHABLE(); + } +} + +void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +{ + // Get the raw indices for an indexed draw + if (type != GL_NONE && elementArrayBuffer) + { + gl::Buffer *indexBuffer = elementArrayBuffer; + BufferImpl *storage = indexBuffer->getImplementation(); + intptr_t offset = reinterpret_cast(indices); + indices = static_cast(storage->getData()) + offset; + } + + // TODO: some level 9 hardware supports 32-bit indices; test and store support instead + const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; + + if (!mLineLoopIB) + { + mLineLoopIB = new StreamingIndexBufferInterface(this); + if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType)) + { + delete mLineLoopIB; + mLineLoopIB = NULL; + + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + // Checked by Renderer11::applyPrimitiveType + ASSERT(count >= 0); + + 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); + } + + const unsigned int spaceNeeded = (static_cast(count) + 1) * indexTypeSize; + if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, indexType)) + { + ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + void* mappedMemory = NULL; + unsigned int offset; + if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) + { + ERR("Could not map index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + if (indexType == GL_UNSIGNED_SHORT) + fillLineLoopIndices(type, count, indices, reinterpret_cast(mappedMemory)); + else + fillLineLoopIndices(type, count, indices, reinterpret_cast(mappedMemory)); + unsigned int indexBufferOffset = offset; + + if (!mLineLoopIB->unmapBuffer()) + { + ERR("Could not unmap index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer()); + ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); + DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); + + if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) + { + mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); + mAppliedIB = d3dIndexBuffer; + mAppliedIBFormat = indexFormat; + mAppliedIBOffset = indexBufferOffset; + } + + mDeviceContext->DrawIndexed(count + 1, 0, -minIndex); +} + +void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances) +{ + // Get the raw indices for an indexed draw + if (type != GL_NONE && elementArrayBuffer) + { + gl::Buffer *indexBuffer = elementArrayBuffer; + BufferImpl *storage = indexBuffer->getImplementation(); + intptr_t offset = reinterpret_cast(indices); + indices = static_cast(storage->getData()) + offset; + } + + const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT; + + if (!mTriangleFanIB) + { + mTriangleFanIB = new StreamingIndexBufferInterface(this); + if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType)) + { + delete mTriangleFanIB; + mTriangleFanIB = NULL; + + ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + // Checked by Renderer11::applyPrimitiveType + ASSERT(count >= 3); + + const unsigned int numTris = count - 2; + + 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); + } + + const unsigned int spaceNeeded = (numTris * 3) * indexTypeSize; + if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, indexType)) + { + ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN."); + return gl::error(GL_OUT_OF_MEMORY); + } + + void* mappedMemory = NULL; + unsigned int offset; + if (!mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) + { + ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN."); + return gl::error(GL_OUT_OF_MEMORY); + } + + if (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()) + { + ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN."); + return gl::error(GL_OUT_OF_MEMORY); + } + + IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer()); + ID3D11Buffer *d3dIndexBuffer = indexBuffer->getBuffer(); + DXGI_FORMAT indexFormat = indexBuffer->getIndexFormat(); + + if (mAppliedIB != d3dIndexBuffer || mAppliedIBFormat != indexFormat || mAppliedIBOffset != indexBufferOffset) + { + mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); + mAppliedIB = d3dIndexBuffer; + mAppliedIBFormat = indexFormat; + mAppliedIBOffset = indexBufferOffset; + } + + if (instances > 0) + { + mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0); + } + else + { + mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex); + } +} + +void 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); + ShaderExecutable *geometryExe = programBinary->getGeometryExecutable(); + + ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL); + + ID3D11PixelShader *pixelShader = NULL; + // Skip pixel shader if we're doing rasterizer discard. + if (!rasterizerDiscard) + { + pixelShader = (pixelExe ? ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader() : NULL); + } + + ID3D11GeometryShader *geometryShader = NULL; + if (transformFeedbackActive) + { + geometryShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getStreamOutShader() : NULL); + } + else if (mCurRasterState.pointDrawMode) + { + geometryShader = (geometryExe ? ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader() : NULL); + } + + bool dirtyUniforms = false; + + if (vertexShader != mAppliedVertexShader) + { + mDeviceContext->VSSetShader(vertexShader, NULL, 0); + mAppliedVertexShader = vertexShader; + dirtyUniforms = true; + } + + if (geometryShader != mAppliedGeometryShader) + { + mDeviceContext->GSSetShader(geometryShader, NULL, 0); + mAppliedGeometryShader = geometryShader; + dirtyUniforms = true; + } + + if (geometryExe && mCurRasterState.pointDrawMode) + { + mCurPointGeometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader(); + } + else + { + mCurPointGeometryShader = NULL; + } + + if (pixelShader != mAppliedPixelShader) + { + mDeviceContext->PSSetShader(pixelShader, NULL, 0); + mAppliedPixelShader = pixelShader; + dirtyUniforms = true; + } + + if (dirtyUniforms) + { + programBinary->dirtyAllUniforms(); + } +} + +void Renderer11::applyUniforms(const gl::ProgramBinary &programBinary) +{ + const std::vector &uniformArray = programBinary.getUniforms(); + + unsigned int totalRegisterCountVS = 0; + unsigned int totalRegisterCountPS = 0; + + bool vertexUniformsDirty = false; + bool pixelUniformsDirty = false; + + for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) + { + const gl::LinkedUniform &uniform = *uniformArray[uniformIndex]; + + if (uniform.isReferencedByVertexShader() && !uniform.isSampler()) + { + totalRegisterCountVS += uniform.registerCount; + vertexUniformsDirty = (vertexUniformsDirty || uniform.dirty); + } + + if (uniform.isReferencedByFragmentShader() && !uniform.isSampler()) + { + totalRegisterCountPS += uniform.registerCount; + pixelUniformsDirty = (pixelUniformsDirty || uniform.dirty); + } + } + + const UniformStorage11 *vertexUniformStorage = UniformStorage11::makeUniformStorage11(&programBinary.getVertexUniformStorage()); + const UniformStorage11 *fragmentUniformStorage = UniformStorage11::makeUniformStorage11(&programBinary.getFragmentUniformStorage()); + ASSERT(vertexUniformStorage); + ASSERT(fragmentUniformStorage); + + ID3D11Buffer *vertexConstantBuffer = vertexUniformStorage->getConstantBuffer(); + ID3D11Buffer *pixelConstantBuffer = fragmentUniformStorage->getConstantBuffer(); + + float (*mapVS)[4] = NULL; + float (*mapPS)[4] = NULL; + + if (totalRegisterCountVS > 0 && vertexUniformsDirty) + { + D3D11_MAPPED_SUBRESOURCE map = {0}; + HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + mapVS = (float(*)[4])map.pData; + } + + if (totalRegisterCountPS > 0 && pixelUniformsDirty) + { + D3D11_MAPPED_SUBRESOURCE map = {0}; + HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + mapPS = (float(*)[4])map.pData; + } + + for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) + { + gl::LinkedUniform *uniform = uniformArray[uniformIndex]; + + if (!uniform->isSampler()) + { + unsigned int componentCount = (4 - uniform->registerElement); + + // we assume that uniforms from structs are arranged in struct order in our uniforms list. otherwise we would + // overwrite previously written regions of memory. + + if (uniform->isReferencedByVertexShader() && mapVS) + { + memcpy(&mapVS[uniform->vsRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount); + } + + if (uniform->isReferencedByFragmentShader() && mapPS) + { + memcpy(&mapPS[uniform->psRegisterIndex][uniform->registerElement], uniform->data, uniform->registerCount * sizeof(float) * componentCount); + } + } + } + + if (mapVS) + { + mDeviceContext->Unmap(vertexConstantBuffer, 0); + } + + if (mapPS) + { + mDeviceContext->Unmap(pixelConstantBuffer, 0); + } + + if (mCurrentVertexConstantBuffer != vertexConstantBuffer) + { + mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer); + mCurrentVertexConstantBuffer = vertexConstantBuffer; + } + + if (mCurrentPixelConstantBuffer != pixelConstantBuffer) + { + mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer); + mCurrentPixelConstantBuffer = pixelConstantBuffer; + } + + // Driver uniforms + if (!mDriverConstantBufferVS) + { + D3D11_BUFFER_DESC constantBufferDescription = {0}; + constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants); + constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; + constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDescription.CPUAccessFlags = 0; + constantBufferDescription.MiscFlags = 0; + constantBufferDescription.StructureByteStride = 0; + + HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + + mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS); + } + + if (!mDriverConstantBufferPS) + { + D3D11_BUFFER_DESC constantBufferDescription = {0}; + constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants); + constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; + constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDescription.CPUAccessFlags = 0; + constantBufferDescription.MiscFlags = 0; + constantBufferDescription.StructureByteStride = 0; + + HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + + mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS); + } + + if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0) + { + mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0); + memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants)); + } + + if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0) + { + mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0); + memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants)); + } + + // needed for the point sprite geometry shader + if (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0 && mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) + { + mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); + mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; + } +} + +void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) +{ + mClear->clearFramebuffer(clearParams, frameBuffer); + invalidateFramebufferSwizzles(frameBuffer); +} + +void Renderer11::markAllStateDirty() +{ + for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) + { + mAppliedRenderTargetSerials[rtIndex] = 0; + } + mAppliedDepthbufferSerial = 0; + mAppliedStencilbufferSerial = 0; + mDepthStencilInitialized = false; + mRenderTargetDescInitialized = false; + + for (int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) + { + mForceSetVertexSamplerStates[i] = true; + mCurVertexSRVs[i] = NULL; + } + for (int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++) + { + mForceSetPixelSamplerStates[i] = true; + mCurPixelSRVs[i] = NULL; + } + + mForceSetBlendState = true; + mForceSetRasterState = true; + mForceSetDepthStencilState = true; + mForceSetScissor = true; + mForceSetViewport = true; + + mAppliedIB = NULL; + mAppliedIBFormat = DXGI_FORMAT_UNKNOWN; + mAppliedIBOffset = 0; + + mAppliedVertexShader = NULL; + mAppliedGeometryShader = NULL; + mCurPointGeometryShader = NULL; + mAppliedPixelShader = NULL; + + for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) + { + mAppliedTFBuffers[i] = NULL; + mAppliedTFOffsets[i] = 0; + } + + memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants)); + memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants)); + + mInputLayoutCache.markDirty(); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; i++) + { + mCurrentConstantBufferVS[i] = -1; + mCurrentConstantBufferPS[i] = -1; + } + + mCurrentVertexConstantBuffer = NULL; + mCurrentPixelConstantBuffer = NULL; + mCurrentGeometryConstantBuffer = NULL; + + mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; +} + +void Renderer11::releaseDeviceResources() +{ + mStateCache.clear(); + mInputLayoutCache.clear(); + + SafeDelete(mVertexDataManager); + SafeDelete(mIndexDataManager); + SafeDelete(mLineLoopIB); + SafeDelete(mTriangleFanIB); + SafeDelete(mBlit); + SafeDelete(mClear); + SafeDelete(mPixelTransfer); + + SafeRelease(mDriverConstantBufferVS); + SafeRelease(mDriverConstantBufferPS); + SafeRelease(mSyncQuery); +} + +void Renderer11::notifyDeviceLost() +{ + mDeviceLost = true; + mDisplay->notifyDeviceLost(); +} + +bool Renderer11::isDeviceLost() +{ + return mDeviceLost; +} + +// set notify to true to broadcast a message to all contexts of the device loss +bool Renderer11::testDeviceLost(bool notify) +{ + bool isLost = false; + + // GetRemovedReason is used to test if the device is removed + HRESULT result = mDevice->GetDeviceRemovedReason(); + isLost = d3d11::isDeviceLostError(result); + + if (isLost) + { + // Log error if this is a new device lost event + if (mDeviceLost == false) + { + ERR("The D3D11 device was removed: 0x%08X", result); + } + + // ensure we note the device loss -- + // we'll probably get this done again by notifyDeviceLost + // but best to remember it! + // Note that we don't want to clear the device loss status here + // -- this needs to be done by resetDevice + mDeviceLost = true; + if (notify) + { + notifyDeviceLost(); + } + } + + return isLost; +} + +bool Renderer11::testDeviceResettable() +{ + // determine if the device is resettable by creating a dummy device + PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); + + if (D3D11CreateDevice == NULL) + { + return false; + } + + D3D_FEATURE_LEVEL featureLevels[] = + { + D3D_FEATURE_LEVEL_11_0, + D3D_FEATURE_LEVEL_10_1, + D3D_FEATURE_LEVEL_10_0, +#if !defined(ANGLE_ENABLE_D3D9) + D3D_FEATURE_LEVEL_9_3, + D3D_FEATURE_LEVEL_9_2, + D3D_FEATURE_LEVEL_9_1, +#endif + }; + + ID3D11Device* dummyDevice; + D3D_FEATURE_LEVEL dummyFeatureLevel; + ID3D11DeviceContext* dummyContext; + + HRESULT result = D3D11CreateDevice(NULL, + D3D_DRIVER_TYPE_HARDWARE, + NULL, + #if defined(_DEBUG) + D3D11_CREATE_DEVICE_DEBUG, + #else + 0, + #endif + featureLevels, + ArraySize(featureLevels), + D3D11_SDK_VERSION, + &dummyDevice, + &dummyFeatureLevel, + &dummyContext); + + if (!mDevice || FAILED(result)) + { + return false; + } + + SafeRelease(dummyContext); + SafeRelease(dummyDevice); + + return true; +} + +void Renderer11::release() +{ + releaseDeviceResources(); + + SafeRelease(mDxgiFactory); + SafeRelease(mDxgiAdapter); + + if (mDeviceContext) + { + mDeviceContext->ClearState(); + mDeviceContext->Flush(); + SafeRelease(mDeviceContext); + } + + SafeRelease(mDevice); + + if (mD3d11Module) + { + FreeLibrary(mD3d11Module); + mD3d11Module = NULL; + } + + if (mDxgiModule) + { + FreeLibrary(mDxgiModule); + mDxgiModule = NULL; + } + + mCompiler.release(); +} + +bool Renderer11::resetDevice() +{ + // recreate everything + release(); + EGLint result = initialize(); + + if (result != EGL_SUCCESS) + { + ERR("Could not reinitialize D3D11 device: %08X", result); + return false; + } + + mDeviceLost = false; + + return true; +} + +DWORD Renderer11::getAdapterVendor() const +{ + return mAdapterDescription.VendorId; +} + +std::string Renderer11::getRendererDescription() const +{ + std::ostringstream rendererString; + + rendererString << mDescription; + rendererString << " Direct3D11"; + + rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel(); + rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel(); + + return rendererString.str(); +} + +GUID Renderer11::getAdapterIdentifier() const +{ + // Use the adapter LUID as our adapter ID + // This number is local to a machine is only guaranteed to be unique between restarts + META_ASSERT(sizeof(LUID) <= sizeof(GUID)); + GUID adapterId = {0}; + memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID)); + return adapterId; +} + +unsigned int Renderer11::getMaxVertexTextureImageUnits() const +{ + META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4; + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return 0; + default: UNREACHABLE(); + return 0; + } +} + +unsigned int Renderer11::getMaxCombinedTextureImageUnits() const +{ + return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits(); +} + +unsigned int Renderer11::getReservedVertexUniformVectors() const +{ + return 0; // Driver uniforms are stored in a separate constant buffer +} + +unsigned int Renderer11::getReservedFragmentUniformVectors() const +{ + return 0; // Driver uniforms are stored in a separate constant buffer +} + +unsigned int Renderer11::getMaxVertexUniformVectors() const +{ + META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); + ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1); + return MAX_VERTEX_UNIFORM_VECTORS_D3D11; +} + +unsigned int Renderer11::getMaxFragmentUniformVectors() const +{ + META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); + ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1); + return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11; +} + +unsigned int Renderer11::getMaxVaryingVectors() const +{ + META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT); + 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 + return 2; +} + +unsigned int Renderer11::getReservedFragmentUniformBuffers() const +{ + // we reserve one buffer for the application uniforms, and one for driver uniforms + 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 + // chrome needs BGRA. Once chrome fixes this, we should always support them. + // PIX doesn't seem to support using share handles, so disable them. + return getRendererExtensions().textureFormatBGRA8888 && !gl::perfActive(); +} + +bool Renderer11::getPostSubBufferSupport() const +{ + // D3D11 does not support present with dirty rectangles until D3D11.1 and DXGI 1.2. + return false; +} + +int Renderer11::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) + { + case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5 + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4 + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: + return D3D10_SHADER_MAJOR_VERSION; // 4 + default: UNREACHABLE(); return 0; + } +} + +int Renderer11::getMinorShaderModel() const +{ + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0 + case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1 + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MINOR_VERSION; // 0 + default: UNREACHABLE(); return 0; + } +} + +int Renderer11::getMinSwapInterval() const +{ + return 0; +} + +int Renderer11::getMaxSwapInterval() const +{ + return 4; +} + +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) +{ + if (source && dest) + { + TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source->getStorageInstance()); + TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest->getStorageInstance()); + + mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); + + dest11->invalidateSwizzleCache(); + + return true; + } + + return false; +} + +bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) +{ + if (source && dest) + { + TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source->getStorageInstance()); + TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest->getStorageInstance()); + + mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); + + dest11->invalidateSwizzleCache(); + + return true; + } + + return false; +} + +bool Renderer11::copyToRenderTarget(TextureStorageInterface3D *dest, TextureStorageInterface3D *source) +{ + if (source && dest) + { + TextureStorage11_3D *source11 = TextureStorage11_3D::makeTextureStorage11_3D(source->getStorageInstance()); + TextureStorage11_3D *dest11 = TextureStorage11_3D::makeTextureStorage11_3D(dest->getStorageInstance()); + + mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); + + dest11->invalidateSwizzleCache(); + + return true; + } + + return false; +} + +bool Renderer11::copyToRenderTarget(TextureStorageInterface2DArray *dest, TextureStorageInterface2DArray *source) +{ + if (source && dest) + { + TextureStorage11_2DArray *source11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(source->getStorageInstance()); + TextureStorage11_2DArray *dest11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(dest->getStorageInstance()); + + mDeviceContext->CopyResource(dest11->getResource(), source11->getResource()); + + dest11->invalidateSwizzleCache(); + + return true; + } + + return false; +} + +bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) +{ + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + if (!colorbuffer) + { + ERR("Failed to retrieve the color buffer from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + if (!sourceRenderTarget) + { + ERR("Failed to retrieve the render target from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); + if (!source) + { + ERR("Failed to retrieve the render target view from the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); + if (!storage11) + { + ERR("Failed to retrieve the texture storage from the destination."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(level)); + if (!destRenderTarget) + { + ERR("Failed to retrieve the render target from the destination storage."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); + if (!dest) + { + ERR("Failed to retrieve the render target view from the destination render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + + gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); + + // Use nearest filtering because source and destination are the same size for the direct + // copy + bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, + destFormat, GL_NEAREST); + + storage11->invalidateSwizzleCacheLevel(level); + + return ret; +} + +bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) +{ + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + if (!colorbuffer) + { + ERR("Failed to retrieve the color buffer from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + if (!sourceRenderTarget) + { + ERR("Failed to retrieve the render target from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); + if (!source) + { + ERR("Failed to retrieve the render target view from the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); + if (!storage11) + { + ERR("Failed to retrieve the texture storage from the destination."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTargetFace(target, level)); + if (!destRenderTarget) + { + ERR("Failed to retrieve the render target from the destination storage."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); + if (!dest) + { + ERR("Failed to retrieve the render target view from the destination render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + + gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); + + // Use nearest filtering because source and destination are the same size for the direct + // copy + bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, + destFormat, GL_NEAREST); + + storage11->invalidateSwizzleCacheLevel(level); + + return ret; +} + +bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface3D *storage, GLint level) +{ + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + if (!colorbuffer) + { + ERR("Failed to retrieve the color buffer from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + if (!sourceRenderTarget) + { + ERR("Failed to retrieve the render target from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); + if (!source) + { + ERR("Failed to retrieve the render target view from the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage->getStorageInstance()); + if (!storage11) + { + ERR("Failed to retrieve the texture storage from the destination."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTargetLayer(level, zOffset)); + if (!destRenderTarget) + { + ERR("Failed to retrieve the render target from the destination storage."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); + if (!dest) + { + ERR("Failed to retrieve the render target view from the destination render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + + gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); + + // Use nearest filtering because source and destination are the same size for the direct + // copy + bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, + destFormat, GL_NEAREST); + + storage11->invalidateSwizzleCacheLevel(level); + + return ret; +} + +bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level) +{ + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + if (!colorbuffer) + { + ERR("Failed to retrieve the color buffer from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + if (!sourceRenderTarget) + { + ERR("Failed to retrieve the render target from the frame buffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); + if (!source) + { + ERR("Failed to retrieve the render target view from the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage->getStorageInstance()); + if (!storage11) + { + SafeRelease(source); + 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)); + if (!destRenderTarget) + { + SafeRelease(source); + ERR("Failed to retrieve the render target from the destination storage."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); + if (!dest) + { + ERR("Failed to retrieve the render target view from the destination render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + gl::Box sourceArea(sourceRect.x, sourceRect.y, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents sourceSize(sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), 1); + + gl::Box destArea(xoffset, yoffset, 0, sourceRect.width, sourceRect.height, 1); + gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1); + + // Use nearest filtering because source and destination are the same size for the direct + // copy + bool ret = mBlit->copyTexture(source, sourceArea, sourceSize, dest, destArea, destSize, NULL, + destFormat, GL_NEAREST); + + storage11->invalidateSwizzleCacheLevel(level); + + return ret; +} + +void Renderer11::unapplyRenderTargets() +{ + setOneTimeRenderTarget(NULL); +} + +void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView) +{ + ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; + + rtvArray[0] = renderTargetView; + + mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, rtvArray, NULL); + + // Do not preserve the serial for this one-time-use render target + for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) + { + mAppliedRenderTargetSerials[rtIndex] = 0; + } +} + +RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth) +{ + SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); + RenderTarget11 *renderTarget = NULL; + + if (depth) + { + // Note: depth stencil may be NULL for 0 sized surfaces + renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(), + swapChain11->getDepthStencilTexture(), + swapChain11->getDepthStencilShaderResource(), + swapChain11->getWidth(), swapChain11->getHeight(), 1); + } + else + { + // Note: render target may be NULL for 0 sized surfaces + renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(), + swapChain11->getOffscreenTexture(), + swapChain11->getRenderTargetShaderResource(), + swapChain11->getWidth(), swapChain11->getHeight(), 1); + } + return renderTarget; +} + +RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples) +{ + RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples); + return renderTarget; +} + +ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers) +{ + ShaderExecutable11 *executable = NULL; + HRESULT result; + + switch (type) + { + case rx::SHADER_VERTEX: + { + ID3D11VertexShader *vertexShader = NULL; + ID3D11GeometryShader *streamOutShader = NULL; + + result = mDevice->CreateVertexShader(function, length, NULL, &vertexShader); + ASSERT(SUCCEEDED(result)); + + if (transformFeedbackVaryings.size() > 0) + { + std::vector soDeclaration; + for (size_t i = 0; i < transformFeedbackVaryings.size(); i++) + { + const gl::LinkedVarying &varying = transformFeedbackVaryings[i]; + GLenum transposedType = gl::TransposeMatrixType(varying.type); + + for (size_t j = 0; j < varying.semanticIndexCount; j++) + { + D3D11_SO_DECLARATION_ENTRY entry = { 0 }; + entry.Stream = 0; + entry.SemanticName = varying.semanticName.c_str(); + entry.SemanticIndex = varying.semanticIndex + j; + entry.StartComponent = 0; + entry.ComponentCount = gl::VariableColumnCount(transposedType); + entry.OutputSlot = (separatedOutputBuffers ? i : 0); + soDeclaration.push_back(entry); + } + } + + result = mDevice->CreateGeometryShaderWithStreamOutput(function, length, soDeclaration.data(), soDeclaration.size(), + NULL, 0, 0, NULL, &streamOutShader); + ASSERT(SUCCEEDED(result)); + } + + if (vertexShader) + { + executable = new ShaderExecutable11(function, length, vertexShader, streamOutShader); + } + } + break; + case rx::SHADER_PIXEL: + { + ID3D11PixelShader *pixelShader = NULL; + + result = mDevice->CreatePixelShader(function, length, NULL, &pixelShader); + ASSERT(SUCCEEDED(result)); + + if (pixelShader) + { + executable = new ShaderExecutable11(function, length, pixelShader); + } + } + break; + case rx::SHADER_GEOMETRY: + { + ID3D11GeometryShader *geometryShader = NULL; + + result = mDevice->CreateGeometryShader(function, length, NULL, &geometryShader); + ASSERT(SUCCEEDED(result)); + + if (geometryShader) + { + executable = new ShaderExecutable11(function, length, geometryShader); + } + } + break; + default: + UNREACHABLE(); + break; + } + + return executable; +} + +ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, D3DWorkaroundType workaround) +{ + const char *profileType = NULL; + switch (type) + { + case rx::SHADER_VERTEX: + profileType = "vs"; + break; + case rx::SHADER_PIXEL: + profileType = "ps"; + break; + case rx::SHADER_GEOMETRY: + profileType = "gs"; + break; + default: + UNREACHABLE(); + return NULL; + } + + const char *profileVersion = NULL; + switch (mFeatureLevel) + { + case D3D_FEATURE_LEVEL_11_0: + profileVersion = "5_0"; + break; + case D3D_FEATURE_LEVEL_10_1: + profileVersion = "4_1"; + break; + case D3D_FEATURE_LEVEL_10_0: + profileVersion = "4_0"; + break; + case D3D_FEATURE_LEVEL_9_3: + profileVersion = "4_0_level_9_3"; + break; + case D3D_FEATURE_LEVEL_9_2: + profileVersion = "4_0_level_9_2"; + break; + case D3D_FEATURE_LEVEL_9_1: + profileVersion = "4_0_level_9_1"; + break; + default: + UNREACHABLE(); + return NULL; + } + + char profile[32]; + snprintf(profile, ArraySize(profile), "%s_%s", profileType, profileVersion); + + UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL0; + + if (gl::perfActive()) + { +#ifndef NDEBUG + flags = D3DCOMPILE_SKIP_OPTIMIZATION; +#endif + + flags |= D3DCOMPILE_DEBUG; + + std::string sourcePath = getTempPath(); + std::string sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(shaderHLSL); + writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); + } + + // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. + // Try the default flags first and if compilation fails, try some alternatives. + const UINT extraFlags[] = + { + flags, + flags | D3DCOMPILE_SKIP_VALIDATION, + flags | D3DCOMPILE_SKIP_OPTIMIZATION + }; + + const static char *extraFlagNames[] = + { + "default", + "skip validation", + "skip optimization" + }; + + int attempts = ArraySize(extraFlags); + + ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts); + if (!binary) + { + return NULL; + } + + ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type, + transformFeedbackVaryings, separatedOutputBuffers); + SafeRelease(binary); + + return executable; +} + +rx::UniformStorage *Renderer11::createUniformStorage(size_t storageSize) +{ + return new UniformStorage11(this, storageSize); +} + +VertexBuffer *Renderer11::createVertexBuffer() +{ + return new VertexBuffer11(this); +} + +IndexBuffer *Renderer11::createIndexBuffer() +{ + return new IndexBuffer11(this); +} + +BufferImpl *Renderer11::createBuffer() +{ + return new Buffer11(this); +} + +VertexArrayImpl *Renderer11::createVertexArray() +{ + return new VertexArray11(this); +} + +QueryImpl *Renderer11::createQuery(GLenum type) +{ + return new Query11(this, type); +} + +FenceImpl *Renderer11::createFence() +{ + return new Fence11(this); +} + +bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const +{ + ASSERT(getRendererExtensions().pixelBufferObject); + + // sRGB formats do not work with D3D11 buffer SRVs + if (gl::GetColorEncoding(internalFormat) == GL_SRGB) + { + return false; + } + + // We cannot support direct copies to non-color-renderable formats + if (gl_d3d11::GetRTVFormat(internalFormat) != DXGI_FORMAT_UNKNOWN) + { + return false; + } + + // We skip all 3-channel formats since sometimes format support is missing + if (gl::GetComponentCount(internalFormat) == 3) + { + return false; + } + + // We don't support formats which we can't represent without conversion + if (getNativeTextureFormat(internalFormat) != internalFormat) + { + return false; + } + + return true; +} + +bool Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +{ + ASSERT(supportsFastCopyBufferToTexture(destinationFormat)); + return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat, sourcePixelsType, destArea); +} + +bool Renderer11::getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource) +{ + ASSERT(colorbuffer != NULL); + + RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); + if (renderTarget) + { + *subresourceIndex = renderTarget->getSubresourceIndex(); + + ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView(); + if (colorBufferRTV) + { + ID3D11Resource *textureResource = NULL; + colorBufferRTV->GetResource(&textureResource); + + if (textureResource) + { + HRESULT result = textureResource->QueryInterface(__uuidof(ID3D11Texture2D), (void**)resource); + SafeRelease(textureResource); + + if (SUCCEEDED(result)) + { + return true; + } + else + { + ERR("Failed to extract the ID3D11Texture2D from the render target resource, " + "HRESULT: 0x%X.", result); + } + } + } + } + + return false; +} + +bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, + const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) +{ + if (blitRenderTarget) + { + gl::FramebufferAttachment *readBuffer = readTarget->getReadColorbuffer(); + + if (!readBuffer) + { + ERR("Failed to retrieve the read buffer from the read framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget *readRenderTarget = readBuffer->getRenderTarget(); + + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + if (drawTarget->isEnabledColorAttachment(colorAttachment)) + { + gl::FramebufferAttachment *drawBuffer = drawTarget->getColorbuffer(colorAttachment); + + if (!drawBuffer) + { + ERR("Failed to retrieve the draw buffer from the draw framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget(); + + if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, + blitRenderTarget, false, false)) + { + return false; + } + } + } + } + + if (blitDepth || blitStencil) + { + gl::FramebufferAttachment *readBuffer = readTarget->getDepthOrStencilbuffer(); + gl::FramebufferAttachment *drawBuffer = drawTarget->getDepthOrStencilbuffer(); + + if (!readBuffer) + { + ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + if (!drawBuffer) + { + ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + RenderTarget *readRenderTarget = readBuffer->getDepthStencil(); + RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil(); + + if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, + false, blitDepth, blitStencil)) + { + return false; + } + } + + invalidateFramebufferSwizzles(drawTarget); + + 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) +{ + ID3D11Texture2D *colorBufferTexture = NULL; + unsigned int subresourceIndex = 0; + + gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer(); + + if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) + { + gl::Rectangle area; + area.x = x; + area.y = y; + area.width = width; + area.height = height; + + if (pack.pixelBuffer.get() != NULL) + { + rx::Buffer11 *packBufferStorage = Buffer11::makeBuffer11(pack.pixelBuffer.get()->getImplementation()); + PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast(pixels)); + packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams); + } + else + { + readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels); + } + + SafeRelease(colorBufferTexture); + } +} + +Image *Renderer11::createImage() +{ + return new Image11(); +} + +void Renderer11::generateMipmap(Image *dest, Image *src) +{ + Image11 *dest11 = Image11::makeImage11(dest); + Image11 *src11 = Image11::makeImage11(src); + Image11::generateMipmap(dest11, src11); +} + +TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain) +{ + SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); + return new TextureStorage11_2D(this, swapChain11); +} + +TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) +{ + return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels); +} + +TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) +{ + return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels); +} + +TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +{ + return new TextureStorage11_3D(this, internalformat, renderTarget, width, height, depth, levels); +} + +TextureStorage *Renderer11::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +{ + return new TextureStorage11_2DArray(this, internalformat, renderTarget, width, height, depth, levels); +} + +Texture2DImpl *Renderer11::createTexture2D() +{ + return new TextureD3D_2D(this); +} + +TextureCubeImpl *Renderer11::createTextureCube() +{ + return new TextureD3D_Cube(this); +} + +Texture3DImpl *Renderer11::createTexture3D() +{ + return new TextureD3D_3D(this); +} + +Texture2DArrayImpl *Renderer11::createTexture2DArray() +{ + return new TextureD3D_2DArray(this); +} + +void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void *pixels) +{ + ASSERT(area.width >= 0); + ASSERT(area.height >= 0); + + D3D11_TEXTURE2D_DESC textureDesc; + texture->GetDesc(&textureDesc); + + // Clamp read region to the defined texture boundaries, preventing out of bounds reads + // and reads of uninitialized data. + gl::Rectangle safeArea; + safeArea.x = gl::clamp(area.x, 0, static_cast(textureDesc.Width)); + safeArea.y = gl::clamp(area.y, 0, static_cast(textureDesc.Height)); + safeArea.width = gl::clamp(area.width + std::min(area.x, 0), 0, + static_cast(textureDesc.Width) - safeArea.x); + safeArea.height = gl::clamp(area.height + std::min(area.y, 0), 0, + static_cast(textureDesc.Height) - safeArea.y); + + ASSERT(safeArea.x >= 0 && safeArea.y >= 0); + ASSERT(safeArea.x + safeArea.width <= static_cast(textureDesc.Width)); + ASSERT(safeArea.y + safeArea.height <= static_cast(textureDesc.Height)); + + if (safeArea.width == 0 || safeArea.height == 0) + { + // no work to do + return; + } + + D3D11_TEXTURE2D_DESC stagingDesc; + stagingDesc.Width = safeArea.width; + stagingDesc.Height = safeArea.height; + stagingDesc.MipLevels = 1; + stagingDesc.ArraySize = 1; + stagingDesc.Format = textureDesc.Format; + stagingDesc.SampleDesc.Count = 1; + stagingDesc.SampleDesc.Quality = 0; + stagingDesc.Usage = D3D11_USAGE_STAGING; + stagingDesc.BindFlags = 0; + stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stagingDesc.MiscFlags = 0; + + ID3D11Texture2D* stagingTex = NULL; + HRESULT result = mDevice->CreateTexture2D(&stagingDesc, NULL, &stagingTex); + if (FAILED(result)) + { + ERR("Failed to create staging texture for readPixels, HRESULT: 0x%X.", result); + return; + } + + ID3D11Texture2D* srcTex = NULL; + if (textureDesc.SampleDesc.Count > 1) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = textureDesc.Width; + resolveDesc.Height = textureDesc.Height; + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = textureDesc.Format; + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = D3D11_USAGE_DEFAULT; + resolveDesc.BindFlags = 0; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + result = mDevice->CreateTexture2D(&resolveDesc, NULL, &srcTex); + if (FAILED(result)) + { + ERR("Failed to create resolve texture for readPixels, HRESULT: 0x%X.", result); + SafeRelease(stagingTex); + return; + } + + mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format); + subResource = 0; + } + else + { + srcTex = texture; + srcTex->AddRef(); + } + + D3D11_BOX srcBox; + srcBox.left = static_cast(safeArea.x); + srcBox.right = static_cast(safeArea.x + safeArea.width); + srcBox.top = static_cast(safeArea.y); + srcBox.bottom = static_cast(safeArea.y + safeArea.height); + srcBox.front = 0; + srcBox.back = 1; + + mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox); + + SafeRelease(srcTex); + + PackPixelsParams packParams(safeArea, format, type, outputPitch, pack, 0); + packPixels(stagingTex, packParams, pixels); + + SafeRelease(stagingTex); +} + +void Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams ¶ms, void *pixelsOut) +{ + D3D11_TEXTURE2D_DESC textureDesc; + readTexture->GetDesc(&textureDesc); + + D3D11_MAPPED_SUBRESOURCE mapping; + HRESULT hr = mDeviceContext->Map(readTexture, 0, D3D11_MAP_READ, 0, &mapping); + UNUSED_ASSERTION_VARIABLE(hr); + ASSERT(SUCCEEDED(hr)); + + unsigned char *source; + int inputPitch; + if (params.pack.reverseRowOrder) + { + source = static_cast(mapping.pData) + mapping.RowPitch * (params.area.height - 1); + inputPitch = -static_cast(mapping.RowPitch); + } + else + { + source = static_cast(mapping.pData); + inputPitch = static_cast(mapping.RowPitch); + } + + 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) + { + unsigned char *dest = static_cast(pixelsOut) + params.offset; + for (int y = 0; y < params.area.height; y++) + { + memcpy(dest + y * params.outputPitch, source + y * inputPitch, params.area.width * sourcePixelSize); + } + } + else + { + GLenum destInternalFormat = gl::GetSizedInternalFormat(params.format, params.type); + GLuint destPixelSize = gl::GetPixelBytes(destInternalFormat); + + ColorCopyFunction fastCopyFunc = d3d11::GetFastCopyFunction(textureDesc.Format, params.format, params.type); + if (fastCopyFunc) + { + // Fast copy is possible through some special function + for (int y = 0; y < params.area.height; y++) + { + for (int x = 0; x < params.area.width; x++) + { + void *dest = static_cast(pixelsOut) + params.offset + y * params.outputPitch + x * destPixelSize; + void *src = static_cast(source) + y * inputPitch + x * sourcePixelSize; + + fastCopyFunc(src, dest); + } + } + } + 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. + META_ASSERT(sizeof(temp) >= sizeof(gl::ColorF) && + sizeof(temp) >= sizeof(gl::ColorUI) && + sizeof(temp) >= sizeof(gl::ColorI)); + + for (int y = 0; y < params.area.height; y++) + { + for (int x = 0; x < params.area.width; x++) + { + void *dest = static_cast(pixelsOut) + params.offset + y * params.outputPitch + x * destPixelSize; + void *src = static_cast(source) + y * inputPitch + x * sourcePixelSize; + + // readFunc and writeFunc will be using the same type of color, CopyTexImage + // will not allow the copy otherwise. + readFunc(src, temp); + writeFunc(temp, dest); + } + } + } + } + + mDeviceContext->Unmap(readTexture, 0); +} + +bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, + RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, + bool colorBlit, bool depthBlit, bool stencilBlit) +{ + // Since blitRenderbufferRect is called for each render buffer that needs to be blitted, + // it should never be the case that both color and depth/stencil need to be blitted at + // at the same time. + ASSERT(colorBlit != (depthBlit || stencilBlit)); + + bool result = true; + + RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget); + if (!drawRenderTarget) + { + ERR("Failed to retrieve the draw render target from the draw framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11Resource *drawTexture = drawRenderTarget11->getTexture(); + unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); + ID3D11RenderTargetView *drawRTV = drawRenderTarget11->getRenderTargetView(); + ID3D11DepthStencilView *drawDSV = drawRenderTarget11->getDepthStencilView(); + + RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget); + if (!readRenderTarget) + { + ERR("Failed to retrieve the read render target from the read framebuffer."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + ID3D11Resource *readTexture = NULL; + ID3D11ShaderResourceView *readSRV = NULL; + unsigned int readSubresource = 0; + if (readRenderTarget->getSamples() > 0) + { + ID3D11Resource *unresolvedResource = readRenderTarget11->getTexture(); + ID3D11Texture2D *unresolvedTexture = d3d11::DynamicCastComObject(unresolvedResource); + + if (unresolvedTexture) + { + readTexture = resolveMultisampledTexture(unresolvedTexture, readRenderTarget11->getSubresourceIndex()); + readSubresource = 0; + + SafeRelease(unresolvedTexture); + + HRESULT hresult = mDevice->CreateShaderResourceView(readTexture, NULL, &readSRV); + if (FAILED(hresult)) + { + SafeRelease(readTexture); + return gl::error(GL_OUT_OF_MEMORY, false); + } + } + } + else + { + readTexture = readRenderTarget11->getTexture(); + readTexture->AddRef(); + readSubresource = readRenderTarget11->getSubresourceIndex(); + readSRV = readRenderTarget11->getShaderResourceView(); + readSRV->AddRef(); + } + + if (!readTexture || !readSRV) + { + SafeRelease(readTexture); + SafeRelease(readSRV); + ERR("Failed to retrieve the read render target view from the read render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + gl::Extents readSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); + gl::Extents drawSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); + + bool scissorNeeded = scissor && gl::ClipRectangle(drawRect, *scissor, NULL); + + bool wholeBufferCopy = !scissorNeeded && + readRect.x == 0 && readRect.width == readSize.width && + readRect.y == 0 && readRect.height == readSize.height && + drawRect.x == 0 && drawRect.width == drawSize.width && + drawRect.y == 0 && drawRect.height == drawSize.height; + + bool stretchRequired = readRect.width != drawRect.width || readRect.height != drawRect.height; + + bool flipRequired = readRect.width < 0 || readRect.height < 0 || drawRect.width < 0 || drawRect.height < 0; + + bool outOfBounds = readRect.x < 0 || readRect.x + readRect.width > readSize.width || + readRect.y < 0 || readRect.y + readRect.height > readSize.height || + drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width || + drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height; + + bool hasDepth = gl::GetDepthBits(drawRenderTarget11->getActualFormat()) > 0; + bool hasStencil = gl::GetStencilBits(drawRenderTarget11->getActualFormat()) > 0; + bool partialDSBlit = (hasDepth && depthBlit) != (hasStencil && stencilBlit); + + if (readRenderTarget11->getActualFormat() == drawRenderTarget->getActualFormat() && + !stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit && + (!(depthBlit || stencilBlit) || wholeBufferCopy)) + { + UINT dstX = drawRect.x; + UINT dstY = drawRect.y; + + D3D11_BOX readBox; + readBox.left = readRect.x; + readBox.right = readRect.x + readRect.width; + readBox.top = readRect.y; + readBox.bottom = readRect.y + readRect.height; + readBox.front = 0; + readBox.back = 1; + + if (scissorNeeded) + { + // drawRect is guaranteed to have positive width and height because stretchRequired is false. + ASSERT(drawRect.width >= 0 || drawRect.height >= 0); + + if (drawRect.x < scissor->x) + { + dstX = scissor->x; + readBox.left += (scissor->x - drawRect.x); + } + if (drawRect.y < scissor->y) + { + dstY = scissor->y; + readBox.top += (scissor->y - drawRect.y); + } + if (drawRect.x + drawRect.width > scissor->x + scissor->width) + { + readBox.right -= ((drawRect.x + drawRect.width) - (scissor->x + scissor->width)); + } + if (drawRect.y + drawRect.height > scissor->y + scissor->height) + { + readBox.bottom -= ((drawRect.y + drawRect.height) - (scissor->y + scissor->height)); + } + } + + // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox + // We also require complete framebuffer copies for depth-stencil blit. + D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox; + + mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, dstX, dstY, 0, + readTexture, readSubresource, pSrcBox); + result = true; + } + else + { + gl::Box readArea(readRect.x, readRect.y, 0, readRect.width, readRect.height, 1); + gl::Box drawArea(drawRect.x, drawRect.y, 0, drawRect.width, drawRect.height, 1); + + if (depthBlit && stencilBlit) + { + result = mBlit->copyDepthStencil(readTexture, readSubresource, readArea, readSize, + drawTexture, drawSubresource, drawArea, drawSize, + scissor); + } + else if (depthBlit) + { + result = mBlit->copyDepth(readSRV, readArea, readSize, drawDSV, drawArea, drawSize, + scissor); + } + else if (stencilBlit) + { + result = mBlit->copyStencil(readTexture, readSubresource, readArea, readSize, + drawTexture, drawSubresource, drawArea, drawSize, + scissor); + } + else + { + GLenum format = gl::GetFormat(drawRenderTarget->getInternalFormat()); + result = mBlit->copyTexture(readSRV, readArea, readSize, drawRTV, drawArea, drawSize, + scissor, format, filter); + } + } + + SafeRelease(readTexture); + SafeRelease(readSRV); + + return result; +} + +ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource) +{ + D3D11_TEXTURE2D_DESC textureDesc; + source->GetDesc(&textureDesc); + + if (textureDesc.SampleDesc.Count > 1) + { + D3D11_TEXTURE2D_DESC resolveDesc; + resolveDesc.Width = textureDesc.Width; + resolveDesc.Height = textureDesc.Height; + resolveDesc.MipLevels = 1; + resolveDesc.ArraySize = 1; + resolveDesc.Format = textureDesc.Format; + resolveDesc.SampleDesc.Count = 1; + resolveDesc.SampleDesc.Quality = 0; + resolveDesc.Usage = textureDesc.Usage; + resolveDesc.BindFlags = textureDesc.BindFlags; + resolveDesc.CPUAccessFlags = 0; + resolveDesc.MiscFlags = 0; + + ID3D11Texture2D *resolveTexture = NULL; + HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture); + if (FAILED(result)) + { + ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result); + return NULL; + } + + mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format); + return resolveTexture; + } + else + { + source->AddRef(); + return source; + } +} + +void Renderer11::invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel) +{ + ASSERT(attachment->isTexture()); + TextureStorage *texStorage = attachment->getTextureStorage(); + if (texStorage) + { + TextureStorage11 *texStorage11 = TextureStorage11::makeTextureStorage11(texStorage); + if (!texStorage11) + { + ERR("texture storage pointer unexpectedly null."); + return; + } + + texStorage11->invalidateSwizzleCacheLevel(mipLevel); + } +} + +void Renderer11::invalidateFramebufferSwizzles(gl::Framebuffer *framebuffer) +{ + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(colorAttachment); + if (attachment && attachment->isTexture()) + { + invalidateFBOAttachmentSwizzles(attachment, attachment->mipLevel()); + } + } + + gl::FramebufferAttachment *depthAttachment = framebuffer->getDepthbuffer(); + if (depthAttachment && depthAttachment->isTexture()) + { + invalidateFBOAttachmentSwizzles(depthAttachment, depthAttachment->mipLevel()); + } + + gl::FramebufferAttachment *stencilAttachment = framebuffer->getStencilbuffer(); + if (stencilAttachment && stencilAttachment->isTexture()) + { + invalidateFBOAttachmentSwizzles(stencilAttachment, stencilAttachment->mipLevel()); + } +} + +bool Renderer11::getLUID(LUID *adapterLuid) const +{ + adapterLuid->HighPart = 0; + adapterLuid->LowPart = 0; + + if (!mDxgiAdapter) + { + return false; + } + + DXGI_ADAPTER_DESC adapterDesc; + if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc))) + { + return false; + } + + *adapterLuid = adapterDesc.AdapterLuid; + return true; +} + +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); +} + +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; +} + +void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const +{ + d3d11_gl::GenerateCaps(mDevice, outCaps, outTextureCaps, outExtensions); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h new file mode 100644 index 0000000000..a31f15ee64 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h @@ -0,0 +1,375 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer11.h: Defines a back-end specific class for the D3D11 renderer. + +#ifndef LIBGLESV2_RENDERER_RENDERER11_H_ +#define LIBGLESV2_RENDERER_RENDERER11_H_ + +#include "common/angleutils.h" +#include "libGLESv2/angletypes.h" +#include "common/mathutil.h" + +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/d3d/HLSLCompiler.h" +#include "libGLESv2/renderer/d3d/d3d11/RenderStateCache.h" +#include "libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h" +#include "libGLESv2/renderer/RenderTarget.h" + +namespace gl +{ +class FramebufferAttachment; +} + +namespace rx +{ + +class VertexDataManager; +class IndexDataManager; +class StreamingIndexBufferInterface; +class Blit11; +class Clear11; +class PixelTransfer11; +struct PackPixelsParams; + +enum +{ + MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024, + MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024 +}; + +class Renderer11 : public Renderer +{ + public: + Renderer11(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay); + virtual ~Renderer11(); + + static Renderer11 *makeRenderer11(Renderer *renderer); + + virtual EGLint initialize(); + virtual bool resetDevice(); + + virtual int generateConfigs(ConfigDesc **configDescList); + virtual void deleteConfigs(ConfigDesc *configDescList); + + virtual void sync(bool block); + + virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + + virtual void 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 bool 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 void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); + virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport); + + virtual bool applyPrimitiveType(GLenum mode, GLsizei count); + virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); + virtual void applyShaders(gl::ProgramBinary *programBinary, 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 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 void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); + + virtual void markAllStateDirty(); + + // lost device + void notifyDeviceLost(); + virtual bool isDeviceLost(); + virtual bool testDeviceLost(bool notify); + virtual bool testDeviceResettable(); + + virtual DWORD getAdapterVendor() const; + 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 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); + + // RenderTarget creation + virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); + virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples); + + // Shader operations + virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers); + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, D3DWorkaroundType workaround); + virtual UniformStorage *createUniformStorage(size_t storageSize); + + // Image operations + virtual Image *createImage(); + virtual void generateMipmap(Image *dest, Image *source); + virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); + virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); + virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels); + virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); + virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); + + // Texture creation + virtual Texture2DImpl *createTexture2D(); + virtual TextureCubeImpl *createTextureCube(); + virtual Texture3DImpl *createTexture3D(); + virtual Texture2DArrayImpl *createTexture2DArray(); + + // Buffer creation + virtual BufferImpl *createBuffer(); + virtual VertexBuffer *createVertexBuffer(); + virtual IndexBuffer *createIndexBuffer(); + + // Vertex Array creation + virtual VertexArrayImpl *createVertexArray(); + + // Query and Fence creation + virtual QueryImpl *createQuery(GLenum type); + virtual FenceImpl *createFence(); + + // D3D11-renderer specific methods + ID3D11Device *getDevice() { return mDevice; } + ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; + IDXGIFactory *getDxgiFactory() { return mDxgiFactory; }; + bool isLevel9() { return mFeatureLevel <= D3D_FEATURE_LEVEL_9_3; } + + Blit11 *getBlitter() { return mBlit; } + + // Buffer-to-texture and Texture-to-buffer copies + virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const; + virtual bool fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + + 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); + + 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; + + private: + DISALLOW_COPY_AND_ASSIGN(Renderer11); + + 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); + + void readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format, + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void *pixels); + + bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, + RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor, + bool colorBlit, bool depthBlit, bool stencilBlit); + ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); + + static void invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel); + static void invalidateFramebufferSwizzles(gl::Framebuffer *framebuffer); + + HMODULE mD3d11Module; + HMODULE mDxgiModule; + EGLNativeDisplayType mDc; + EGLint mRequestedDisplay; + + HLSLCompiler mCompiler; + + bool mDeviceLost; + + void initializeDevice(); + void releaseDeviceResources(); + int getMinorShaderModel() const; + void release(); + + 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; + unsigned int mAppliedStencilbufferSerial; + bool mDepthStencilInitialized; + bool mRenderTargetDescInitialized; + 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]; + + bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; + gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; + + // Currently applied textures + ID3D11ShaderResourceView *mCurVertexSRVs[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + ID3D11ShaderResourceView *mCurPixelSRVs[gl::MAX_TEXTURE_IMAGE_UNITS]; + + // Currently applied blend state + bool mForceSetBlendState; + gl::BlendState mCurBlendState; + gl::ColorF mCurBlendColor; + unsigned int mCurSampleMask; + + // Currently applied rasterizer state + bool mForceSetRasterState; + gl::RasterizerState mCurRasterState; + + // Currently applied depth stencil state + bool mForceSetDepthStencilState; + gl::DepthStencilState mCurDepthStencilState; + int mCurStencilRef; + int mCurStencilBackRef; + + // Currently applied scissor rectangle + bool mForceSetScissor; + bool mScissorEnabled; + gl::Rectangle mCurScissor; + + // Currently applied viewport + bool mForceSetViewport; + gl::Rectangle mCurViewport; + float mCurNear; + float mCurFar; + + // Currently applied primitive topology + D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology; + + // Currently applied index buffer + ID3D11Buffer *mAppliedIB; + DXGI_FORMAT mAppliedIBFormat; + unsigned int mAppliedIBOffset; + + // Currently applied transform feedback buffers + ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; + GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; + + // Currently applied shaders + ID3D11VertexShader *mAppliedVertexShader; + ID3D11GeometryShader *mAppliedGeometryShader; + ID3D11GeometryShader *mCurPointGeometryShader; + ID3D11PixelShader *mAppliedPixelShader; + + dx_VertexConstants mVertexConstants; + dx_VertexConstants mAppliedVertexConstants; + ID3D11Buffer *mDriverConstantBufferVS; + ID3D11Buffer *mCurrentVertexConstantBuffer; + unsigned int mCurrentConstantBufferVS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; + + dx_PixelConstants mPixelConstants; + dx_PixelConstants mAppliedPixelConstants; + ID3D11Buffer *mDriverConstantBufferPS; + ID3D11Buffer *mCurrentPixelConstantBuffer; + unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS]; + + ID3D11Buffer *mCurrentGeometryConstantBuffer; + + // Vertex, index and input layouts + VertexDataManager *mVertexDataManager; + IndexDataManager *mIndexDataManager; + InputLayoutCache mInputLayoutCache; + + StreamingIndexBufferInterface *mLineLoopIB; + StreamingIndexBufferInterface *mTriangleFanIB; + + // Texture copy resources + Blit11 *mBlit; + PixelTransfer11 *mPixelTransfer; + + // Masked clear resources + Clear11 *mClear; + + // Sync query + ID3D11Query *mSyncQuery; + + ID3D11Device *mDevice; + D3D_FEATURE_LEVEL mFeatureLevel; + ID3D11DeviceContext *mDeviceContext; + IDXGIAdapter *mDxgiAdapter; + DXGI_ADAPTER_DESC mAdapterDescription; + char mDescription[128]; + IDXGIFactory *mDxgiFactory; +}; + +} +#endif // LIBGLESV2_RENDERER_RENDERER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp new file mode 100644 index 0000000000..5a7c987494 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp @@ -0,0 +1,112 @@ +#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 +// found in the LICENSE file. +// + +// ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader +// executable implementation details. + +#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h" + +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ + +ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable) + : ShaderExecutable(function, length) +{ + mPixelExecutable = executable; + mVertexExecutable = NULL; + mGeometryExecutable = NULL; + mStreamOutExecutable = NULL; +} + +ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut) + : ShaderExecutable(function, length) +{ + mVertexExecutable = executable; + mPixelExecutable = NULL; + mGeometryExecutable = NULL; + mStreamOutExecutable = streamOut; +} + +ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable) + : ShaderExecutable(function, length) +{ + mGeometryExecutable = executable; + mVertexExecutable = NULL; + mPixelExecutable = NULL; + mStreamOutExecutable = NULL; +} + +ShaderExecutable11::~ShaderExecutable11() +{ + SafeRelease(mVertexExecutable); + SafeRelease(mPixelExecutable); + SafeRelease(mGeometryExecutable); + SafeRelease(mStreamOutExecutable); +} + +ShaderExecutable11 *ShaderExecutable11::makeShaderExecutable11(ShaderExecutable *executable) +{ + ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable11*, executable)); + return static_cast(executable); +} + +ID3D11VertexShader *ShaderExecutable11::getVertexShader() const +{ + return mVertexExecutable; +} + +ID3D11PixelShader *ShaderExecutable11::getPixelShader() const +{ + return mPixelExecutable; +} + +ID3D11GeometryShader *ShaderExecutable11::getGeometryShader() const +{ + return mGeometryExecutable; +} + +ID3D11GeometryShader *ShaderExecutable11::getStreamOutShader() const +{ + return mStreamOutExecutable; +} + +UniformStorage11::UniformStorage11(Renderer11 *renderer, size_t initialSize) + : UniformStorage(initialSize), + mConstantBuffer(NULL) +{ + ID3D11Device *d3d11Device = renderer->getDevice(); + + if (initialSize > 0) + { + D3D11_BUFFER_DESC constantBufferDescription = {0}; + constantBufferDescription.ByteWidth = initialSize; + constantBufferDescription.Usage = D3D11_USAGE_DYNAMIC; + constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + constantBufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + constantBufferDescription.MiscFlags = 0; + constantBufferDescription.StructureByteStride = 0; + + HRESULT result = d3d11Device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + } +} + +UniformStorage11::~UniformStorage11() +{ + SafeRelease(mConstantBuffer); +} + +const UniformStorage11 *UniformStorage11::makeUniformStorage11(const UniformStorage *uniformStorage) +{ + ASSERT(HAS_DYNAMIC_TYPE(const UniformStorage11*, uniformStorage)); + return static_cast(uniformStorage); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h new file mode 100644 index 0000000000..74a1e03915 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h @@ -0,0 +1,61 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderExecutable11.h: Defines a D3D11-specific class to contain shader +// executable implementation details. + +#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ +#define LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ + +#include "libGLESv2/renderer/ShaderExecutable.h" + +namespace rx +{ +class Renderer11; +class UniformStorage11; + +class ShaderExecutable11 : public ShaderExecutable +{ + public: + ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable); + ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut); + ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable); + + virtual ~ShaderExecutable11(); + + static ShaderExecutable11 *makeShaderExecutable11(ShaderExecutable *executable); + + ID3D11PixelShader *getPixelShader() const; + ID3D11VertexShader *getVertexShader() const; + ID3D11GeometryShader *getGeometryShader() const; + ID3D11GeometryShader *getStreamOutShader() const; + + private: + DISALLOW_COPY_AND_ASSIGN(ShaderExecutable11); + + ID3D11PixelShader *mPixelExecutable; + ID3D11VertexShader *mVertexExecutable; + ID3D11GeometryShader *mGeometryExecutable; + ID3D11GeometryShader *mStreamOutExecutable; +}; + +class UniformStorage11 : public UniformStorage +{ + public: + UniformStorage11(Renderer11 *renderer, size_t initialSize); + virtual ~UniformStorage11(); + + static const UniformStorage11 *makeUniformStorage11(const UniformStorage *uniformStorage); + + ID3D11Buffer *getConstantBuffer() const { return mConstantBuffer; } + + private: + ID3D11Buffer *mConstantBuffer; +}; + +} + +#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp new file mode 100644 index 0000000000..0341df10f9 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp @@ -0,0 +1,713 @@ +#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 +// found in the LICENSE file. +// + +// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. + +#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h" + +#include "common/platform.h" +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h" +#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h" + +namespace rx +{ + +SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle, + GLenum backBufferFormat, GLenum depthBufferFormat) + : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) +{ + mSwapChain = NULL; + mBackBufferTexture = NULL; + mBackBufferRTView = NULL; + mOffscreenTexture = NULL; + mOffscreenRTView = NULL; + mOffscreenSRView = NULL; + mDepthStencilTexture = NULL; + mDepthStencilDSView = NULL; + mDepthStencilSRView = NULL; + mQuadVB = NULL; + mPassThroughSampler = NULL; + mPassThroughIL = NULL; + mPassThroughVS = NULL; + mPassThroughPS = NULL; + mWidth = -1; + mHeight = -1; + mViewportWidth = -1; + mViewportHeight = -1; + mSwapInterval = 0; + mAppCreatedShareHandle = mShareHandle != NULL; + mPassThroughResourcesInit = false; +} + +SwapChain11::~SwapChain11() +{ + release(); +} + +void SwapChain11::release() +{ + SafeRelease(mSwapChain); + SafeRelease(mBackBufferTexture); + SafeRelease(mBackBufferRTView); + SafeRelease(mOffscreenTexture); + SafeRelease(mOffscreenRTView); + SafeRelease(mOffscreenSRView); + SafeRelease(mDepthStencilTexture); + SafeRelease(mDepthStencilDSView); + SafeRelease(mDepthStencilSRView); + SafeRelease(mQuadVB); + SafeRelease(mPassThroughSampler); + SafeRelease(mPassThroughIL); + SafeRelease(mPassThroughVS); + SafeRelease(mPassThroughPS); + + if (!mAppCreatedShareHandle) + { + mShareHandle = NULL; + } +} + +void SwapChain11::releaseOffscreenTexture() +{ + SafeRelease(mOffscreenTexture); + SafeRelease(mOffscreenRTView); + SafeRelease(mOffscreenSRView); + SafeRelease(mDepthStencilTexture); + SafeRelease(mDepthStencilDSView); + SafeRelease(mDepthStencilSRView); +} + +EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight) +{ + ID3D11Device *device = mRenderer->getDevice(); + + ASSERT(device != NULL); + + // D3D11 does not allow zero size textures + ASSERT(backbufferWidth >= 1); + ASSERT(backbufferHeight >= 1); + +#if !defined(ANGLE_PLATFORM_WINRT) + // Preserve the render target content + ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; + if (previousOffscreenTexture) + { + previousOffscreenTexture->AddRef(); + } + const int previousWidth = mWidth; + const int previousHeight = mHeight; +#endif + + releaseOffscreenTexture(); + + // If the app passed in a share handle, open the resource + // See EGL_ANGLE_d3d_share_handle_client_buffer + if (mAppCreatedShareHandle) + { + ID3D11Resource *tempResource11; + HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11); + + if (FAILED(result)) + { + ERR("Failed to open the swap chain pbuffer share handle: %08lX", result); + release(); + return EGL_BAD_PARAMETER; + } + + result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture); + SafeRelease(tempResource11); + + if (FAILED(result)) + { + ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result); + release(); + return EGL_BAD_PARAMETER; + } + + // Validate offscreen texture parameters + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; + mOffscreenTexture->GetDesc(&offscreenTextureDesc); + + if (offscreenTextureDesc.Width != (UINT)backbufferWidth + || offscreenTextureDesc.Height != (UINT)backbufferHeight + || offscreenTextureDesc.Format != gl_d3d11::GetTexFormat(mBackBufferFormat) + || offscreenTextureDesc.MipLevels != 1 + || offscreenTextureDesc.ArraySize != 1) + { + ERR("Invalid texture parameters in the shared offscreen texture pbuffer"); + release(); + return EGL_BAD_PARAMETER; + } + } + else + { + const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport(); + + D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; + offscreenTextureDesc.Width = backbufferWidth; + offscreenTextureDesc.Height = backbufferHeight; + offscreenTextureDesc.Format = gl_d3d11::GetTexFormat(mBackBufferFormat); + offscreenTextureDesc.MipLevels = 1; + offscreenTextureDesc.ArraySize = 1; + offscreenTextureDesc.SampleDesc.Count = 1; + offscreenTextureDesc.SampleDesc.Quality = 0; + offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT; + offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; + offscreenTextureDesc.CPUAccessFlags = 0; + offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0; + + HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture); + + if (FAILED(result)) + { + ERR("Could not create offscreen texture: %08lX", result); + release(); + + if (d3d11::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + d3d11::SetDebugName(mOffscreenTexture, "Offscreen back buffer texture"); + + // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client + if (useSharedResource) + { + IDXGIResource *offscreenTextureResource = NULL; + result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource); + + // Fall back to no share handle on failure + if (FAILED(result)) + { + ERR("Could not query offscreen texture resource: %08lX", result); + } + else + { + result = offscreenTextureResource->GetSharedHandle(&mShareHandle); + SafeRelease(offscreenTextureResource); + + if (FAILED(result)) + { + mShareHandle = NULL; + ERR("Could not get offscreen texture shared handle: %08lX", result); + } + } + } + } + + + D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc; + offscreenRTVDesc.Format = gl_d3d11::GetRTVFormat(mBackBufferFormat); + offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + offscreenRTVDesc.Texture2D.MipSlice = 0; + + HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, &offscreenRTVDesc, &mOffscreenRTView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mOffscreenRTView, "Offscreen back buffer render target"); + + D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc; + offscreenSRVDesc.Format = gl_d3d11::GetSRVFormat(mBackBufferFormat); + offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + offscreenSRVDesc.Texture2D.MostDetailedMip = 0; + offscreenSRVDesc.Texture2D.MipLevels = -1; + + result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource"); + + if (mDepthBufferFormat != GL_NONE) + { + D3D11_TEXTURE2D_DESC depthStencilTextureDesc; + depthStencilTextureDesc.Width = backbufferWidth; + depthStencilTextureDesc.Height = backbufferHeight; + depthStencilTextureDesc.Format = gl_d3d11::GetTexFormat(mDepthBufferFormat); + depthStencilTextureDesc.MipLevels = 1; + depthStencilTextureDesc.ArraySize = 1; + depthStencilTextureDesc.SampleDesc.Count = 1; + depthStencilTextureDesc.SampleDesc.Quality = 0; + depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT; + depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE; + depthStencilTextureDesc.CPUAccessFlags = 0; + depthStencilTextureDesc.MiscFlags = 0; + + result = device->CreateTexture2D(&depthStencilTextureDesc, NULL, &mDepthStencilTexture); + if (FAILED(result)) + { + ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); + release(); + + if (d3d11::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + d3d11::SetDebugName(mDepthStencilTexture, "Offscreen depth stencil texture"); + + D3D11_DEPTH_STENCIL_VIEW_DESC depthStencilDesc; + depthStencilDesc.Format = gl_d3d11::GetDSVFormat(mDepthBufferFormat); + depthStencilDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + depthStencilDesc.Flags = 0; + depthStencilDesc.Texture2D.MipSlice = 0; + + result = device->CreateDepthStencilView(mDepthStencilTexture, &depthStencilDesc, &mDepthStencilDSView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthStencilDSView, "Offscreen depth stencil view"); + + D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc; + depthStencilSRVDesc.Format = gl_d3d11::GetSRVFormat(mDepthBufferFormat); + depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + depthStencilSRVDesc.Texture2D.MostDetailedMip = 0; + depthStencilSRVDesc.Texture2D.MipLevels = -1; + + result = device->CreateShaderResourceView(mDepthStencilTexture, &depthStencilSRVDesc, &mDepthStencilSRView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mDepthStencilSRView, "Offscreen depth stencil shader resource"); + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; +#if !defined(ANGLE_PLATFORM_WINRT) || WINAPI_FAMILY==WINAPI_FAMILY_PC_APP + mViewportWidth = backbufferWidth; + mViewportHeight = backbufferHeight; +#endif + +#if !defined(ANGLE_PLATFORM_WINRT) + if (previousOffscreenTexture != NULL) + { + D3D11_BOX sourceBox = {0}; + sourceBox.left = 0; + sourceBox.right = std::min(previousWidth, mWidth); + sourceBox.top = std::max(previousHeight - mHeight, 0); + sourceBox.bottom = previousHeight; + sourceBox.front = 0; + sourceBox.back = 1; + + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + const int yoffset = std::max(mHeight - previousHeight, 0); + deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox); + + SafeRelease(previousOffscreenTexture); + + if (mSwapChain) + { + swapRect(0, 0, mWidth, mHeight, SWAP_NORMAL); + } + } +#endif + + return EGL_SUCCESS; +} + +EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) +{ + ID3D11Device *device = mRenderer->getDevice(); + + if (device == NULL) + { + return EGL_BAD_ACCESS; + } + + // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains + if (backbufferWidth < 1 || backbufferHeight < 1) + { + return EGL_SUCCESS; + } + + // Can only call resize if we have already created our swap buffer and resources + ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); + + SafeRelease(mBackBufferTexture); + SafeRelease(mBackBufferRTView); + + // Resize swap chain + HRESULT result; +#if !defined(ANGLE_PLATFORM_WINRT) || WINAPI_FAMILY==WINAPI_FAMILY_PC_APP // Windows phone swap chain is never resized, only the texture is +#if !defined(ANGLE_PLATFORM_WINRT) + const int bufferCount = 1; +#else + const int bufferCount = 2; +#endif + DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::GetTexFormat(mBackBufferFormat); + result = mSwapChain->ResizeBuffers(bufferCount, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0); + + if (FAILED(result)) + { + ERR("Error resizing swap chain buffers: 0x%08X", result); + release(); + + if (d3d11::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } +#endif + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); + ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { + d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); + } + + result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); + ASSERT(SUCCEEDED(result)); + if (SUCCEEDED(result)) + { + d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); + } + + return resetOffscreenTexture(backbufferWidth, backbufferHeight); +} + +EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) +{ + ID3D11Device *device = mRenderer->getDevice(); + + if (device == NULL) + { + return EGL_BAD_ACCESS; + } + + // Release specific resources to free up memory for the new render target, while the + // old render target still exists for the purpose of preserving its contents. + SafeRelease(mSwapChain); + SafeRelease(mBackBufferTexture); + SafeRelease(mBackBufferRTView); + + mSwapInterval = static_cast(swapInterval); + if (mSwapInterval > 4) + { + // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range + return EGL_BAD_PARAMETER; + } + + // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains + if (backbufferWidth < 1 || backbufferHeight < 1) + { + releaseOffscreenTexture(); + return EGL_SUCCESS; + } + + if (mWindow) + { + 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.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; + swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.BufferCount = 1; + swapChainDesc.OutputWindow = mWindow; + swapChainDesc.Windowed = TRUE; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + swapChainDesc.Flags = 0; + + HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); +#else + IDXGIFactory2 *factory2; + HRESULT result = factory->QueryInterface(IID_PPV_ARGS(&factory2)); + ASSERT(SUCCEEDED(result)); + + DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; + swapChainDesc.Width = 0; + swapChainDesc.Height = 0; + swapChainDesc.Format = gl_d3d11::GetTexFormat(mBackBufferFormat); + swapChainDesc.SampleDesc.Count = 1; + swapChainDesc.SampleDesc.Quality = 0; + swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapChainDesc.Stereo = FALSE; + swapChainDesc.Flags = 0; +#if WINAPI_FAMILY==WINAPI_FAMILY_PC_APP + swapChainDesc.Scaling = DXGI_SCALING_NONE; + swapChainDesc.BufferCount = 2; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; +#elif WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP + swapChainDesc.BufferCount = 1; + swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; +#endif + + IDXGISwapChain1 *swapChain; + result = factory2->CreateSwapChainForCoreWindow(device, mWindow, &swapChainDesc, NULL, &swapChain); + mSwapChain = swapChain; + HRESULT hr = swapChain->GetDesc1(&swapChainDesc); + ASSERT(SUCCEEDED(hr)); + mViewportWidth = swapChainDesc.Width; + mViewportHeight = swapChainDesc.Height; +#endif + + if (FAILED(result)) + { + ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); + release(); + + if (d3d11::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); + + result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); + } + + // If we are resizing the swap chain, we don't wish to recreate all the static resources + if (!mPassThroughResourcesInit) + { + mPassThroughResourcesInit = true; + initPassThroughResources(); + } + + return resetOffscreenTexture(backbufferWidth, backbufferHeight); +} + +void SwapChain11::initPassThroughResources() +{ + ID3D11Device *device = mRenderer->getDevice(); + + ASSERT(device != NULL); + + // Make sure our resources are all not allocated, when we create + ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL); + ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL); + + D3D11_BUFFER_DESC vbDesc; + vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; + vbDesc.Usage = D3D11_USAGE_DYNAMIC; + vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + vbDesc.MiscFlags = 0; + vbDesc.StructureByteStride = 0; + + HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer"); + + D3D11_SAMPLER_DESC samplerDesc; + samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; + samplerDesc.MipLODBias = 0.0f; + samplerDesc.MaxAnisotropy = 0; + samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; + samplerDesc.BorderColor[0] = 0.0f; + samplerDesc.BorderColor[1] = 0.0f; + samplerDesc.BorderColor[2] = 0.0f; + samplerDesc.BorderColor[3] = 0.0f; + samplerDesc.MinLOD = 0; + samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; + + result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler"); + + D3D11_INPUT_ELEMENT_DESC quadLayout[] = + { + { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + }; + + result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), &mPassThroughIL); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout"); + + result = device->CreateVertexShader(g_VS_Passthrough2D, sizeof(g_VS_Passthrough2D), NULL, &mPassThroughVS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader"); + + result = device->CreatePixelShader(g_PS_PassthroughRGBA2D, sizeof(g_PS_PassthroughRGBA2D), NULL, &mPassThroughPS); + ASSERT(SUCCEEDED(result)); + d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader"); +} + +// parameters should be validated/clamped by caller +EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags) +{ + if (!mSwapChain) + { + return EGL_SUCCESS; + } + + ID3D11Device *device = mRenderer->getDevice(); + ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); + + // Set vertices + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + return EGL_BAD_ACCESS; + } + + d3d11::PositionTexCoordVertex *vertices = static_cast(mappedResource.pData); + + // Create a quad in homogeneous coordinates + float x1 = (x / float(mWidth)) * 2.0f - 1.0f; + float y1 = (y / float(mHeight)) * 2.0f - 1.0f; + float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; + float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; + + float u1 = x / float(mWidth); + float v1 = y / float(mHeight); + float u2 = (x + width) / float(mWidth); + float v2 = (y + height) / float(mHeight); + + const int rotateL = flags & SWAP_ROTATE_90; + const int rotateR = flags & SWAP_ROTATE_270; + + d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1); + d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2); + d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1); + d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2); + + deviceContext->Unmap(mQuadVB, 0); + + static UINT stride = sizeof(d3d11::PositionTexCoordVertex); + static UINT startIdx = 0; + deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx); + + // Apply state + deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); + + static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; + deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); + + deviceContext->RSSetState(NULL); + + // Apply shaders + deviceContext->IASetInputLayout(mPassThroughIL); + deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); + deviceContext->VSSetShader(mPassThroughVS, NULL, 0); + deviceContext->PSSetShader(mPassThroughPS, NULL, 0); + deviceContext->GSSetShader(NULL, NULL, 0); + + // Apply render targets + mRenderer->setOneTimeRenderTarget(mBackBufferRTView); + + // Set the viewport + D3D11_VIEWPORT viewport; + viewport.TopLeftX = 0; + viewport.TopLeftY = 0; + viewport.Width = mViewportWidth; + viewport.Height = mViewportHeight; + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + deviceContext->RSSetViewports(1, &viewport); + + // Apply textures + deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView); + deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); + + // Draw + deviceContext->Draw(4, 0); + +#if ANGLE_FORCE_VSYNC_OFF + result = mSwapChain->Present(0, 0); +#else + result = mSwapChain->Present(mSwapInterval, 0); +#endif + + if (result == DXGI_ERROR_DEVICE_REMOVED) + { + HRESULT removedReason = device->GetDeviceRemovedReason(); + UNUSED_TRACE_VARIABLE(removedReason); + ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason); + return EGL_CONTEXT_LOST; + } + else if (result == DXGI_ERROR_DEVICE_RESET) + { + ERR("Present failed: the D3D11 device was reset from a bad command."); + return EGL_CONTEXT_LOST; + } + else if (FAILED(result)) + { + ERR("Present failed with error code 0x%08X", result); + } + + // Unbind + static ID3D11ShaderResourceView *const nullSRV = NULL; + deviceContext->PSSetShaderResources(0, 1, &nullSRV); + + mRenderer->unapplyRenderTargets(); + mRenderer->markAllStateDirty(); + + return EGL_SUCCESS; +} + +ID3D11Texture2D *SwapChain11::getOffscreenTexture() +{ + return mOffscreenTexture; +} + +ID3D11RenderTargetView *SwapChain11::getRenderTarget() +{ + return mOffscreenRTView; +} + +ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource() +{ + return mOffscreenSRView; +} + +ID3D11DepthStencilView *SwapChain11::getDepthStencil() +{ + return mDepthStencilDSView; +} + +ID3D11ShaderResourceView * SwapChain11::getDepthStencilShaderResource() +{ + return mDepthStencilSRView; +} + +ID3D11Texture2D *SwapChain11::getDepthStencilTexture() +{ + return mDepthStencilTexture; +} + +SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain)); + return static_cast(swapChain); +} + +void SwapChain11::recreate() +{ + // possibly should use this method instead of reset +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h new file mode 100644 index 0000000000..b30b78568a --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h @@ -0,0 +1,82 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChain11.h: Defines a back-end specific class for the D3D11 swap chain. + +#ifndef LIBGLESV2_RENDERER_SWAPCHAIN11_H_ +#define LIBGLESV2_RENDERER_SWAPCHAIN11_H_ + +#include "common/angleutils.h" +#include "libGLESv2/renderer/SwapChain.h" + +namespace rx +{ +class Renderer11; + +class SwapChain11 : public SwapChain +{ + public: + SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle, + GLenum backBufferFormat, GLenum depthBufferFormat); + virtual ~SwapChain11(); + + EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); + virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint flags); + virtual void recreate(); + + virtual ID3D11Texture2D *getOffscreenTexture(); + virtual ID3D11RenderTargetView *getRenderTarget(); + virtual ID3D11ShaderResourceView *getRenderTargetShaderResource(); + + virtual ID3D11Texture2D *getDepthStencilTexture(); + virtual ID3D11DepthStencilView *getDepthStencil(); + virtual ID3D11ShaderResourceView *getDepthStencilShaderResource(); + + EGLint getWidth() const { return mWidth; } + EGLint getHeight() const { return mHeight; } + + static SwapChain11 *makeSwapChain11(SwapChain *swapChain); + + private: + DISALLOW_COPY_AND_ASSIGN(SwapChain11); + + void release(); + void initPassThroughResources(); + void releaseOffscreenTexture(); + EGLint resetOffscreenTexture(int backbufferWidth, int backbufferHeight); + + Renderer11 *mRenderer; + EGLint mHeight; + EGLint mWidth; + EGLint mViewportWidth; + EGLint mViewportHeight; + bool mAppCreatedShareHandle; + unsigned int mSwapInterval; + bool mPassThroughResourcesInit; + + IDXGISwapChain *mSwapChain; + + ID3D11Texture2D *mBackBufferTexture; + ID3D11RenderTargetView *mBackBufferRTView; + + ID3D11Texture2D *mOffscreenTexture; + ID3D11RenderTargetView *mOffscreenRTView; + ID3D11ShaderResourceView *mOffscreenSRView; + + ID3D11Texture2D *mDepthStencilTexture; + ID3D11DepthStencilView *mDepthStencilDSView; + ID3D11ShaderResourceView *mDepthStencilSRView; + + ID3D11Buffer *mQuadVB; + ID3D11SamplerState *mPassThroughSampler; + ID3D11InputLayout *mPassThroughIL; + ID3D11VertexShader *mPassThroughVS; + ID3D11PixelShader *mPassThroughPS; +}; + +} +#endif // LIBGLESV2_RENDERER_SWAPCHAIN11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp new file mode 100644 index 0000000000..00b81b7c92 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp @@ -0,0 +1,1559 @@ +#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 +// found in the LICENSE file. +// + +// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived +// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. + +#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h" + +#include "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 "common/utilities.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +TextureStorage11::SwizzleCacheValue::SwizzleCacheValue() + : swizzleRed(GL_NONE), swizzleGreen(GL_NONE), swizzleBlue(GL_NONE), swizzleAlpha(GL_NONE) +{ +} + +TextureStorage11::SwizzleCacheValue::SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha) + : swizzleRed(red), swizzleGreen(green), swizzleBlue(blue), swizzleAlpha(alpha) +{ +} + +bool TextureStorage11::SwizzleCacheValue::operator==(const SwizzleCacheValue &other) const +{ + return swizzleRed == other.swizzleRed && + swizzleGreen == other.swizzleGreen && + swizzleBlue == other.swizzleBlue && + swizzleAlpha == other.swizzleAlpha; +} + +bool TextureStorage11::SwizzleCacheValue::operator!=(const SwizzleCacheValue &other) const +{ + return !(*this == other); +} + +TextureStorage11::SRVKey::SRVKey(int baseLevel, int mipLevels, bool swizzle) + : baseLevel(baseLevel), mipLevels(mipLevels), swizzle(swizzle) +{ +} + +bool TextureStorage11::SRVKey::operator==(const SRVKey &rhs) const +{ + return baseLevel == rhs.baseLevel && + mipLevels == rhs.mipLevels && + swizzle == rhs.swizzle; +} + +TextureStorage11::SRVCache::~SRVCache() +{ + for (size_t i = 0; i < cache.size(); i++) + { + SafeRelease(cache[i].srv); + } +} + +ID3D11ShaderResourceView *TextureStorage11::SRVCache::find(const SRVKey &key) const +{ + for (size_t i = 0; i < cache.size(); i++) + { + if (cache[i].key == key) + { + return cache[i].srv; + } + } + + return NULL; +} + +ID3D11ShaderResourceView *TextureStorage11::SRVCache::add(const SRVKey &key, ID3D11ShaderResourceView *srv) +{ + SRVPair pair = {key, srv}; + cache.push_back(pair); + + return srv; +} + +TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags) + : mBindFlags(bindFlags), + mTopLevel(0), + mMipLevels(0), + mTextureFormat(DXGI_FORMAT_UNKNOWN), + mShaderResourceFormat(DXGI_FORMAT_UNKNOWN), + mRenderTargetFormat(DXGI_FORMAT_UNKNOWN), + mDepthStencilFormat(DXGI_FORMAT_UNKNOWN), + mTextureWidth(0), + mTextureHeight(0), + mTextureDepth(0) +{ + mRenderer = Renderer11::makeRenderer11(renderer); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mLevelSRVs[i] = NULL; + } +} + +TextureStorage11::~TextureStorage11() +{ + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + SafeRelease(mLevelSRVs[level]); + } +} + +TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage)); + return static_cast(storage); +} + +DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, bool renderTarget) +{ + UINT bindFlags = 0; + + if (gl_d3d11::GetSRVFormat(internalFormat) != DXGI_FORMAT_UNKNOWN) + { + bindFlags |= D3D11_BIND_SHADER_RESOURCE; + } + if (gl_d3d11::GetDSVFormat(internalFormat) != DXGI_FORMAT_UNKNOWN) + { + bindFlags |= D3D11_BIND_DEPTH_STENCIL; + } + if (gl_d3d11::GetRTVFormat(internalFormat) != DXGI_FORMAT_UNKNOWN && renderTarget) + { + bindFlags |= D3D11_BIND_RENDER_TARGET; + } + + return bindFlags; +} + +UINT TextureStorage11::getBindFlags() const +{ + return mBindFlags; +} + +int TextureStorage11::getTopLevel() const +{ + return mTopLevel; +} + +bool TextureStorage11::isRenderTarget() const +{ + return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0; +} + +bool TextureStorage11::isManaged() const +{ + return false; +} + +int TextureStorage11::getLevelCount() const +{ + return mMipLevels - mTopLevel; +} + +int TextureStorage11::getLevelWidth(int mipLevel) const +{ + return std::max(static_cast(mTextureWidth) >> mipLevel, 1); +} + +int TextureStorage11::getLevelHeight(int mipLevel) const +{ + return std::max(static_cast(mTextureHeight) >> mipLevel, 1); +} + +int TextureStorage11::getLevelDepth(int mipLevel) const +{ + return std::max(static_cast(mTextureDepth) >> mipLevel, 1); +} + +UINT TextureStorage11::getSubresourceIndex(int mipLevel, int layerTarget) const +{ + UINT index = 0; + if (getResource()) + { + index = D3D11CalcSubresource(mipLevel, layerTarget, mMipLevels); + } + return index; +} + +ID3D11ShaderResourceView *TextureStorage11::getSRV(const gl::SamplerState &samplerState) +{ + bool swizzleRequired = samplerState.swizzleRequired(); + bool mipmapping = IsMipmapFiltered(samplerState); + unsigned int mipLevels = mipmapping ? (samplerState.maxLevel - samplerState.baseLevel) : 1; + + // Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, which corresponds to GL level 0) + mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - samplerState.baseLevel); + + if (swizzleRequired) + { + verifySwizzleExists(samplerState.swizzleRed, samplerState.swizzleGreen, samplerState.swizzleBlue, samplerState.swizzleAlpha); + } + + SRVKey key(samplerState.baseLevel, mipLevels, swizzleRequired); + ID3D11ShaderResourceView *srv = srvCache.find(key); + + if(srv) + { + return srv; + } + + DXGI_FORMAT format = (swizzleRequired ? mSwizzleShaderResourceFormat : mShaderResourceFormat); + ID3D11Resource *texture = swizzleRequired ? getSwizzleTexture() : getResource(); + + srv = createSRV(samplerState.baseLevel, mipLevels, format, texture); + + return srvCache.add(key, srv); +} + +ID3D11ShaderResourceView *TextureStorage11::getSRVLevel(int mipLevel) +{ + if (mipLevel >= 0 && mipLevel < getLevelCount()) + { + if (!mLevelSRVs[mipLevel]) + { + mLevelSRVs[mipLevel] = createSRV(mipLevel, 1, mShaderResourceFormat, getResource()); + } + + return mLevelSRVs[mipLevel]; + } + else + { + return NULL; + } +} + +void TextureStorage11::generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) +{ + SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); + for (int level = 0; level < getLevelCount(); level++) + { + // Check if the swizzle for this level is out of date + if (mSwizzleCache[level] != swizzleTarget) + { + // Need to re-render the swizzle for this level + ID3D11ShaderResourceView *sourceSRV = getSRVLevel(level); + ID3D11RenderTargetView *destRTV = getSwizzleRenderTarget(level); + + gl::Extents size(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); + + Blit11 *blitter = mRenderer->getBlitter(); + + if (blitter->swizzleTexture(sourceSRV, destRTV, size, swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha)) + { + mSwizzleCache[level] = swizzleTarget; + } + else + { + ERR("Failed to swizzle texture."); + } + } + } +} + +void TextureStorage11::invalidateSwizzleCacheLevel(int mipLevel) +{ + if (mipLevel >= 0 && static_cast(mipLevel) < ArraySize(mSwizzleCache)) + { + // The default constructor of SwizzleCacheValue has GL_NONE for all channels which is not a + // valid swizzle combination + mSwizzleCache[mipLevel] = SwizzleCacheValue(); + } +} + +void TextureStorage11::invalidateSwizzleCache() +{ + for (unsigned int mipLevel = 0; mipLevel < ArraySize(mSwizzleCache); mipLevel++) + { + invalidateSwizzleCacheLevel(mipLevel); + } +} + +bool TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, unsigned int sourceSubresource, + int level, int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth) +{ + if (srcTexture) + { + invalidateSwizzleCacheLevel(level); + + gl::Extents texSize(getLevelWidth(level), getLevelHeight(level), getLevelDepth(level)); + gl::Box copyArea(xoffset, yoffset, zoffset, width, height, depth); + + bool fullCopy = copyArea.x == 0 && + copyArea.y == 0 && + copyArea.z == 0 && + copyArea.width == texSize.width && + copyArea.height == texSize.height && + copyArea.depth == texSize.depth; + + ID3D11Resource *dstTexture = getResource(); + unsigned int dstSubresource = getSubresourceIndex(level + mTopLevel, layerTarget); + + ASSERT(dstTexture); + + if (!fullCopy && (d3d11::GetDepthBits(mTextureFormat) > 0 || d3d11::GetStencilBits(mTextureFormat) > 0)) + { + // CopySubresourceRegion cannot copy partial depth stencils, use the blitter instead + Blit11 *blitter = mRenderer->getBlitter(); + + return blitter->copyDepthStencil(srcTexture, sourceSubresource, copyArea, texSize, + dstTexture, dstSubresource, copyArea, texSize, + NULL); + } + else + { + D3D11_BOX srcBox; + srcBox.left = copyArea.x; + srcBox.top = copyArea.y; + srcBox.right = copyArea.x + roundUp((unsigned int)width, d3d11::GetBlockWidth(mTextureFormat)); + srcBox.bottom = copyArea.y + roundUp((unsigned int)height, d3d11::GetBlockHeight(mTextureFormat)); + srcBox.front = copyArea.z; + srcBox.back = copyArea.z + copyArea.depth; + + ID3D11DeviceContext *context = mRenderer->getDeviceContext(); + + context->CopySubresourceRegion(dstTexture, dstSubresource, copyArea.x, copyArea.y, copyArea.z, + srcTexture, sourceSubresource, fullCopy ? NULL : &srcBox); + return true; + } + } + + return false; +} + +void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest) +{ + if (source && dest) + { + ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView(); + ID3D11RenderTargetView *destRTV = dest->getRenderTargetView(); + + if (sourceSRV && destRTV) + { + gl::Box sourceArea(0, 0, 0, source->getWidth(), source->getHeight(), source->getDepth()); + gl::Extents sourceSize(source->getWidth(), source->getHeight(), source->getDepth()); + + gl::Box destArea(0, 0, 0, dest->getWidth(), dest->getHeight(), dest->getDepth()); + gl::Extents destSize(dest->getWidth(), dest->getHeight(), dest->getDepth()); + + Blit11 *blitter = mRenderer->getBlitter(); + + blitter->copyTexture(sourceSRV, sourceArea, sourceSize, destRTV, destArea, destSize, NULL, + gl::GetFormat(source->getInternalFormat()), GL_LINEAR); + } + } +} + +void TextureStorage11::verifySwizzleExists(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha) +{ + SwizzleCacheValue swizzleTarget(swizzleRed, swizzleGreen, swizzleBlue, swizzleAlpha); + for (unsigned int level = 0; level < mMipLevels; level++) + { + ASSERT(mSwizzleCache[level] == swizzleTarget); + } +} + +TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain) + : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE) +{ + mTexture = swapchain->getOffscreenTexture(); + mTexture->AddRef(); + mSwizzleTexture = NULL; + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + mRenderTarget[i] = NULL; + mSwizzleRenderTargets[i] = NULL; + } + + D3D11_TEXTURE2D_DESC texDesc; + mTexture->GetDesc(&texDesc); + mMipLevels = texDesc.MipLevels; + mTextureFormat = texDesc.Format; + mTextureWidth = texDesc.Width; + mTextureHeight = texDesc.Height; + mTextureDepth = 1; + + ID3D11ShaderResourceView *srv = swapchain->getRenderTargetShaderResource(); + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srv->GetDesc(&srvDesc); + mShaderResourceFormat = srvDesc.Format; + + ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget(); + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + offscreenRTV->GetDesc(&rtvDesc); + mRenderTargetFormat = rtvDesc.Format; + + GLenum internalFormat = d3d11_gl::GetInternalFormat(mTextureFormat); + mSwizzleTextureFormat = gl_d3d11::GetSwizzleTexFormat(internalFormat); + mSwizzleShaderResourceFormat = gl_d3d11::GetSwizzleSRVFormat(internalFormat); + mSwizzleRenderTargetFormat = gl_d3d11::GetSwizzleRTVFormat(internalFormat); + + mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; +} + +TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) + : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)) +{ + mTexture = NULL; + mSwizzleTexture = NULL; + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + 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); + + // if the width or height is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (width > 0 && height > 0) + { + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); + + ID3D11Device *device = mRenderer->getDevice(); + + 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.ArraySize = 1; + desc.Format = mTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + gl::error(GL_OUT_OF_MEMORY); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + gl::error(GL_OUT_OF_MEMORY); + } + else + { + mTexture->GetDesc(&desc); + mMipLevels = desc.MipLevels; + mTextureWidth = desc.Width; + mTextureHeight = desc.Height; + mTextureDepth = 1; + } + } +} + +TextureStorage11_2D::~TextureStorage11_2D() +{ + SafeRelease(mTexture); + SafeRelease(mSwizzleTexture); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + SafeDelete(mRenderTarget[i]); + SafeRelease(mSwizzleRenderTargets[i]); + } +} + +TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage)); + return static_cast(storage); +} + +ID3D11Resource *TextureStorage11_2D::getResource() const +{ + return mTexture; +} + +RenderTarget *TextureStorage11_2D::getRenderTarget(int level) +{ + if (level >= 0 && level < getLevelCount()) + { + if (!mRenderTarget[level]) + { + ID3D11ShaderResourceView *srv = getSRVLevel(level); + if (!srv) + { + return NULL; + } + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + level; + + ID3D11RenderTargetView *rtv; + HRESULT result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + } + else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mDepthStencilFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + dsvDesc.Texture2D.MipSlice = mTopLevel + level; + dsvDesc.Flags = 0; + + ID3D11DepthStencilView *dsv; + HRESULT result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); + + if (result == E_OUTOFMEMORY) + { + SafeRelease(srv); + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1); + + // RenderTarget will take ownership of these resources + SafeRelease(dsv); + } + else + { + UNREACHABLE(); + } + } + + return mRenderTarget[level]; + } + else + { + return NULL; + } +} + +ID3D11ShaderResourceView *TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) +{ + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel; + srvDesc.Texture2D.MipLevels = mipLevels; + + ID3D11ShaderResourceView *SRV = NULL; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV); + + if (result == E_OUTOFMEMORY) + { + gl::error(GL_OUT_OF_MEMORY); + } + ASSERT(SUCCEEDED(result)); + + return SRV; +} + +void TextureStorage11_2D::generateMipmap(int level) +{ + invalidateSwizzleCacheLevel(level); + + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); + + generateMipmapLayer(source, dest); +} + +ID3D11Resource *TextureStorage11_2D::getSwizzleTexture() +{ + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = 1; + desc.Format = mSwizzleTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSwizzleTexture; +} + +ID3D11RenderTargetView *TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel) +{ + if (mipLevel >= 0 && mipLevel < getLevelCount()) + { + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = getSwizzleTexture(); + if (!swizzleTexture) + { + return NULL; + } + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtvDesc.Texture2D.MipSlice = mTopLevel + mipLevel; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSwizzleRenderTargets[mipLevel]; + } + else + { + return NULL; + } +} + +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)) +{ + mTexture = NULL; + mSwizzleTexture = NULL; + + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + mSwizzleRenderTargets[level] = NULL; + for (unsigned int face = 0; face < 6; face++) + { + 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); + + // if the size is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (size > 0) + { + // adjust size if needed for compressed textures + int height = size; + d3d11::MakeValidSize(false, mTextureFormat, &size, &height, &mTopLevel); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = size; + desc.Height = size; + desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0); + desc.ArraySize = 6; + desc.Format = mTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + + if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + gl::error(GL_OUT_OF_MEMORY); + } + else + { + mTexture->GetDesc(&desc); + mMipLevels = desc.MipLevels; + mTextureWidth = desc.Width; + mTextureHeight = desc.Height; + mTextureDepth = 1; + } + } +} + +TextureStorage11_Cube::~TextureStorage11_Cube() +{ + SafeRelease(mTexture); + SafeRelease(mSwizzleTexture); + + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + SafeRelease(mSwizzleRenderTargets[level]); + for (unsigned int face = 0; face < 6; face++) + { + SafeDelete(mRenderTarget[face][level]); + } + } +} + +TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage)); + return static_cast(storage); +} + +ID3D11Resource *TextureStorage11_Cube::getResource() const +{ + return mTexture; +} + +RenderTarget *TextureStorage11_Cube::getRenderTargetFace(GLenum faceTarget, int level) +{ + if (level >= 0 && level < getLevelCount()) + { + int faceIndex = TextureD3D_Cube::targetToIndex(faceTarget); + if (!mRenderTarget[faceIndex][level]) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = mShaderResourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + level; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = faceIndex; + srvDesc.Texture2DArray.ArraySize = 1; + + ID3D11ShaderResourceView *srv; + result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + level; + rtvDesc.Texture2DArray.FirstArraySlice = faceIndex; + rtvDesc.Texture2DArray.ArraySize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + SafeRelease(srv); + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + SafeRelease(srv); + } + else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; + dsvDesc.Format = mDepthStencilFormat; + dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; + dsvDesc.Flags = 0; + dsvDesc.Texture2DArray.MipSlice = mTopLevel + level; + dsvDesc.Texture2DArray.FirstArraySlice = faceIndex; + dsvDesc.Texture2DArray.ArraySize = 1; + + ID3D11DepthStencilView *dsv; + result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); + + if (result == E_OUTOFMEMORY) + { + SafeRelease(srv); + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + mRenderTarget[faceIndex][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, getLevelWidth(level), getLevelHeight(level), 1); + + // RenderTarget will take ownership of these resources + SafeRelease(dsv); + SafeRelease(srv); + } + else + { + UNREACHABLE(); + } + } + + return mRenderTarget[faceIndex][level]; + } + else + { + return NULL; + } +} + +ID3D11ShaderResourceView *TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) +{ + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + + // Unnormalized integer cube maps are not supported by DX11; we emulate them as an array of six 2D textures + bool unnormalizedInteger = (d3d11::GetComponentType(mTextureFormat) == GL_INT || + d3d11::GetComponentType(mTextureFormat) == GL_UNSIGNED_INT); + + if(unnormalizedInteger) + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = 0; + srvDesc.Texture2DArray.ArraySize = 6; + } + else + { + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + srvDesc.TextureCube.MipLevels = mipLevels; + srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel; + } + + ID3D11ShaderResourceView *SRV = NULL; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV); + + if (result == E_OUTOFMEMORY) + { + gl::error(GL_OUT_OF_MEMORY); + } + ASSERT(SUCCEEDED(result)); + + return SRV; +} + +void TextureStorage11_Cube::generateMipmap(int faceIndex, int level) +{ + invalidateSwizzleCacheLevel(level); + + 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)); + + generateMipmapLayer(source, dest); +} + +ID3D11Resource *TextureStorage11_Cube::getSwizzleTexture() +{ + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = 6; + desc.Format = mSwizzleTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSwizzleTexture; +} + +ID3D11RenderTargetView *TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel) +{ + if (mipLevel >= 0 && mipLevel < getLevelCount()) + { + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = getSwizzleTexture(); + if (!swizzleTexture) + { + return NULL; + } + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture2DArray.FirstArraySlice = 0; + rtvDesc.Texture2DArray.ArraySize = 6; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSwizzleRenderTargets[mipLevel]; + } + else + { + return NULL; + } +} + +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)) +{ + mTexture = NULL; + mSwizzleTexture = NULL; + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + 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); + + // If the width, height or depth are not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (width > 0 && height > 0 && depth > 0) + { + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE3D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.Depth = depth; + desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0); + desc.Format = mTextureFormat; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture3D(&desc, NULL, &mTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + gl::error(GL_OUT_OF_MEMORY); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + gl::error(GL_OUT_OF_MEMORY); + } + else + { + mTexture->GetDesc(&desc); + mMipLevels = desc.MipLevels; + mTextureWidth = desc.Width; + mTextureHeight = desc.Height; + mTextureDepth = desc.Depth; + } + } +} + +TextureStorage11_3D::~TextureStorage11_3D() +{ + SafeRelease(mTexture); + SafeRelease(mSwizzleTexture); + + for (RenderTargetMap::iterator i = mLevelLayerRenderTargets.begin(); i != mLevelLayerRenderTargets.end(); i++) + { + SafeDelete(i->second); + } + mLevelLayerRenderTargets.clear(); + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) + { + SafeDelete(mLevelRenderTargets[i]); + SafeRelease(mSwizzleRenderTargets[i]); + } +} + +TextureStorage11_3D *TextureStorage11_3D::makeTextureStorage11_3D(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_3D*, storage)); + return static_cast(storage); +} + +ID3D11Resource *TextureStorage11_3D::getResource() const +{ + return mTexture; +} + +ID3D11ShaderResourceView *TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) +{ + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE3D; + srvDesc.Texture3D.MostDetailedMip = baseLevel; + srvDesc.Texture3D.MipLevels = mipLevels; + + ID3D11ShaderResourceView *SRV = NULL; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV); + + if (result == E_OUTOFMEMORY) + { + gl::error(GL_OUT_OF_MEMORY); + } + ASSERT(SUCCEEDED(result)); + + return SRV; +} + +RenderTarget *TextureStorage11_3D::getRenderTarget(int mipLevel) +{ + if (mipLevel >= 0 && mipLevel < getLevelCount()) + { + if (!mLevelRenderTargets[mipLevel]) + { + ID3D11ShaderResourceView *srv = getSRVLevel(mipLevel); + if (!srv) + { + return NULL; + } + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture3D.FirstWSlice = 0; + rtvDesc.Texture3D.WSize = -1; + + ID3D11RenderTargetView *rtv; + HRESULT result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + SafeRelease(srv); + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + mLevelRenderTargets[mipLevel] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), getLevelDepth(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()) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + // TODO, what kind of SRV is expected here? + ID3D11ShaderResourceView *srv = NULL; + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture3D.FirstWSlice = layer; + rtvDesc.Texture3D.WSize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + SafeRelease(srv); + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + mLevelLayerRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + SafeRelease(srv); + } + else + { + UNREACHABLE(); + } + } + + return mLevelLayerRenderTargets[key]; + } + else + { + return NULL; + } +} + +void TextureStorage11_3D::generateMipmap(int level) +{ + invalidateSwizzleCacheLevel(level); + + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); + + generateMipmapLayer(source, dest); +} + +ID3D11Resource *TextureStorage11_3D::getSwizzleTexture() +{ + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE3D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.Depth = mTextureDepth; + desc.MipLevels = mMipLevels; + desc.Format = mSwizzleTextureFormat; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture3D(&desc, NULL, &mSwizzleTexture); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSwizzleTexture; +} + +ID3D11RenderTargetView *TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel) +{ + if (mipLevel >= 0 && mipLevel < getLevelCount()) + { + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = getSwizzleTexture(); + if (!swizzleTexture) + { + return NULL; + } + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D; + rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture3D.FirstWSlice = 0; + rtvDesc.Texture3D.WSize = -1; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSwizzleRenderTargets[mipLevel]; + } + else + { + return NULL; + } +} + +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)) +{ + mTexture = NULL; + mSwizzleTexture = NULL; + + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + 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); + + // if the width, height or depth is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (width > 0 && height > 0 && depth > 0) + { + // adjust size if needed for compressed textures + d3d11::MakeValidSize(false, mTextureFormat, &width, &height, &mTopLevel); + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = width; + desc.Height = height; + desc.MipLevels = ((levels > 0) ? (mTopLevel + levels) : 0); + desc.ArraySize = depth; + desc.Format = mTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = getBindFlags(); + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); + + // this can happen from windows TDR + if (d3d11::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + gl::error(GL_OUT_OF_MEMORY); + } + else if (FAILED(result)) + { + ASSERT(result == E_OUTOFMEMORY); + ERR("Creating image failed."); + gl::error(GL_OUT_OF_MEMORY); + } + else + { + mTexture->GetDesc(&desc); + mMipLevels = desc.MipLevels; + mTextureWidth = desc.Width; + mTextureHeight = desc.Height; + mTextureDepth = desc.ArraySize; + } + } +} + +TextureStorage11_2DArray::~TextureStorage11_2DArray() +{ + SafeRelease(mTexture); + SafeRelease(mSwizzleTexture); + + for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++) + { + SafeRelease(mSwizzleRenderTargets[level]); + } + + for (RenderTargetMap::iterator i = mRenderTargets.begin(); i != mRenderTargets.end(); i++) + { + SafeDelete(i->second); + } + mRenderTargets.clear(); +} + +TextureStorage11_2DArray *TextureStorage11_2DArray::makeTextureStorage11_2DArray(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2DArray*, storage)); + return static_cast(storage); +} + +ID3D11Resource *TextureStorage11_2DArray::getResource() const +{ + return mTexture; +} + +ID3D11ShaderResourceView *TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) +{ + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = format; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + baseLevel; + srvDesc.Texture2DArray.MipLevels = mipLevels; + srvDesc.Texture2DArray.FirstArraySlice = 0; + srvDesc.Texture2DArray.ArraySize = mTextureDepth; + + ID3D11ShaderResourceView *SRV = NULL; + + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, &SRV); + + if (result == E_OUTOFMEMORY) + { + gl::error(GL_OUT_OF_MEMORY); + } + ASSERT(SUCCEEDED(result)); + + return SRV; +} + +RenderTarget *TextureStorage11_2DArray::getRenderTargetLayer(int mipLevel, int layer) +{ + if (mipLevel >= 0 && mipLevel < getLevelCount()) + { + LevelLayerKey key(mipLevel, layer); + if (mRenderTargets.find(key) == mRenderTargets.end()) + { + ID3D11Device *device = mRenderer->getDevice(); + HRESULT result; + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; + srvDesc.Format = mShaderResourceFormat; + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; + srvDesc.Texture2DArray.MostDetailedMip = mTopLevel + mipLevel; + srvDesc.Texture2DArray.MipLevels = 1; + srvDesc.Texture2DArray.FirstArraySlice = layer; + srvDesc.Texture2DArray.ArraySize = 1; + + ID3D11ShaderResourceView *srv; + result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) + { + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture2DArray.FirstArraySlice = layer; + rtvDesc.Texture2DArray.ArraySize = 1; + + ID3D11RenderTargetView *rtv; + result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); + + if (result == E_OUTOFMEMORY) + { + SafeRelease(srv); + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + + mRenderTargets[key] = new RenderTarget11(mRenderer, rtv, mTexture, srv, getLevelWidth(mipLevel), getLevelHeight(mipLevel), 1); + + // RenderTarget will take ownership of these resources + SafeRelease(rtv); + SafeRelease(srv); + } + else + { + UNREACHABLE(); + } + } + + return mRenderTargets[key]; + } + else + { + return NULL; + } +} + +void TextureStorage11_2DArray::generateMipmap(int level) +{ + invalidateSwizzleCacheLevel(level); + for (unsigned int layer = 0; layer < mTextureDepth; layer++) + { + RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level - 1, layer)); + RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTargetLayer(level, layer)); + + generateMipmapLayer(source, dest); + } +} + +ID3D11Resource *TextureStorage11_2DArray::getSwizzleTexture() +{ + if (!mSwizzleTexture) + { + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_TEXTURE2D_DESC desc; + desc.Width = mTextureWidth; + desc.Height = mTextureHeight; + desc.MipLevels = mMipLevels; + desc.ArraySize = mTextureDepth; + desc.Format = mSwizzleTextureFormat; + desc.SampleDesc.Count = 1; + desc.SampleDesc.Quality = 0; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + desc.CPUAccessFlags = 0; + desc.MiscFlags = 0; + + HRESULT result = device->CreateTexture2D(&desc, NULL, &mSwizzleTexture); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSwizzleTexture; +} + +ID3D11RenderTargetView *TextureStorage11_2DArray::getSwizzleRenderTarget(int mipLevel) +{ + if (mipLevel >= 0 && mipLevel < getLevelCount()) + { + if (!mSwizzleRenderTargets[mipLevel]) + { + ID3D11Resource *swizzleTexture = getSwizzleTexture(); + if (!swizzleTexture) + { + return NULL; + } + + ID3D11Device *device = mRenderer->getDevice(); + + D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; + rtvDesc.Format = mSwizzleRenderTargetFormat; + rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; + rtvDesc.Texture2DArray.MipSlice = mTopLevel + mipLevel; + rtvDesc.Texture2DArray.FirstArraySlice = 0; + rtvDesc.Texture2DArray.ArraySize = mTextureDepth; + + HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]); + + if (result == E_OUTOFMEMORY) + { + return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); + } + ASSERT(SUCCEEDED(result)); + } + + return mSwizzleRenderTargets[mipLevel]; + } + else + { + return NULL; + } +} + +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 new file mode 100644 index 0000000000..6be7bac8e2 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h @@ -0,0 +1,278 @@ +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureStorage11.h: Defines the abstract rx::TextureStorage11 class and its concrete derived +// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. + +#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ +#define LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ + +#include "libGLESv2/Texture.h" +#include "libGLESv2/renderer/d3d/TextureStorage.h" + +namespace rx +{ +class RenderTarget; +class RenderTarget11; +class Renderer; +class Renderer11; +class SwapChain11; + +class TextureStorage11 : public TextureStorage +{ + public: + virtual ~TextureStorage11(); + + static TextureStorage11 *makeTextureStorage11(TextureStorage *storage); + + static DWORD GetTextureBindFlags(GLenum internalFormat, bool renderTarget); + + UINT getBindFlags() const; + + 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 void generateMipmap(int level) {}; + virtual void generateMipmap(int face, int level) {}; + + virtual int getTopLevel() const; + virtual bool isRenderTarget() const; + virtual bool isManaged() const; + virtual int getLevelCount() const; + UINT getSubresourceIndex(int mipLevel, int layerTarget) const; + + void generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha); + void invalidateSwizzleCacheLevel(int mipLevel); + void invalidateSwizzleCache(); + + bool updateSubresourceLevel(ID3D11Resource *texture, unsigned int sourceSubresource, int level, + int layerTarget, GLint xoffset, GLint yoffset, GLint zoffset, + GLsizei width, GLsizei height, GLsizei depth); + + protected: + TextureStorage11(Renderer *renderer, UINT bindFlags); + void generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest); + int getLevelWidth(int mipLevel) const; + int getLevelHeight(int mipLevel) const; + int getLevelDepth(int mipLevel) const; + + virtual ID3D11Resource *getSwizzleTexture() = 0; + virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel) = 0; + ID3D11ShaderResourceView *getSRVLevel(int mipLevel); + + virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture) = 0; + + 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; + + DXGI_FORMAT mTextureFormat; + DXGI_FORMAT mShaderResourceFormat; + DXGI_FORMAT mRenderTargetFormat; + DXGI_FORMAT mDepthStencilFormat; + DXGI_FORMAT mSwizzleTextureFormat; + DXGI_FORMAT mSwizzleShaderResourceFormat; + DXGI_FORMAT mSwizzleRenderTargetFormat; + unsigned int mTextureWidth; + unsigned int mTextureHeight; + unsigned int mTextureDepth; + + struct SwizzleCacheValue + { + GLenum swizzleRed; + GLenum swizzleGreen; + GLenum swizzleBlue; + GLenum swizzleAlpha; + + SwizzleCacheValue(); + SwizzleCacheValue(GLenum red, GLenum green, GLenum blue, GLenum alpha); + + bool operator ==(const SwizzleCacheValue &other) const; + bool operator !=(const SwizzleCacheValue &other) const; + }; + SwizzleCacheValue mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + struct SRVKey + { + SRVKey(int baseLevel = 0, int mipLevels = 0, bool swizzle = false); + + bool operator==(const SRVKey &rhs) const; + + int baseLevel; + int mipLevels; + bool swizzle; + }; + + struct SRVPair + { + SRVKey key; + ID3D11ShaderResourceView *srv; + }; + + struct SRVCache + { + ~SRVCache(); + + ID3D11ShaderResourceView *find(const SRVKey &key) const; + ID3D11ShaderResourceView *add(const SRVKey &key, ID3D11ShaderResourceView *srv); + + std::vector cache; + }; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage11); + + const UINT mBindFlags; + + SRVCache srvCache; + ID3D11ShaderResourceView *mLevelSRVs[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_2D : public TextureStorage11 +{ + public: + TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain); + TextureStorage11_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); + virtual ~TextureStorage11_2D(); + + static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage); + + virtual ID3D11Resource *getResource() const; + virtual RenderTarget *getRenderTarget(int level); + + virtual void generateMipmap(int level); + + protected: + virtual ID3D11Resource *getSwizzleTexture(); + virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); + + virtual unsigned int getTextureLevelDepth(int mipLevel) const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D); + + virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture); + + ID3D11Texture2D *mTexture; + RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + ID3D11Texture2D *mSwizzleTexture; + ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_Cube : public TextureStorage11 +{ + public: + TextureStorage11_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels); + virtual ~TextureStorage11_Cube(); + + static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage); + + virtual ID3D11Resource *getResource() const; + virtual RenderTarget *getRenderTargetFace(GLenum faceTarget, int level); + + virtual void generateMipmap(int faceIndex, int level); + + protected: + virtual ID3D11Resource *getSwizzleTexture(); + virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); + + virtual unsigned int getTextureLevelDepth(int mipLevel) const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube); + + virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture); + + ID3D11Texture2D *mTexture; + RenderTarget11 *mRenderTarget[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + ID3D11Texture2D *mSwizzleTexture; + ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_3D : public TextureStorage11 +{ + public: + TextureStorage11_3D(Renderer *renderer, GLenum internalformat, bool renderTarget, + GLsizei width, GLsizei height, GLsizei depth, int levels); + virtual ~TextureStorage11_3D(); + + 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); + + protected: + virtual ID3D11Resource *getSwizzleTexture(); + virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); + + virtual unsigned int getTextureLevelDepth(int mipLevel) const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage11_3D); + + virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture); + + typedef std::pair LevelLayerKey; + typedef std::map RenderTargetMap; + RenderTargetMap mLevelLayerRenderTargets; + + RenderTarget11 *mLevelRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; + + ID3D11Texture3D *mTexture; + ID3D11Texture3D *mSwizzleTexture; + ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +class TextureStorage11_2DArray : public TextureStorage11 +{ + public: + TextureStorage11_2DArray(Renderer *renderer, GLenum internalformat, bool renderTarget, + GLsizei width, GLsizei height, GLsizei depth, int levels); + virtual ~TextureStorage11_2DArray(); + + static TextureStorage11_2DArray *makeTextureStorage11_2DArray(TextureStorage *storage); + + virtual ID3D11Resource *getResource() const; + virtual RenderTarget *getRenderTargetLayer(int mipLevel, int layer); + + virtual void generateMipmap(int level); + + protected: + virtual ID3D11Resource *getSwizzleTexture(); + virtual ID3D11RenderTargetView *getSwizzleRenderTarget(int mipLevel); + + virtual unsigned int getTextureLevelDepth(int mipLevel) const; + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2DArray); + + virtual ID3D11ShaderResourceView *createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture); + + typedef std::pair LevelLayerKey; + typedef std::map RenderTargetMap; + RenderTargetMap mRenderTargets; + + ID3D11Texture2D *mTexture; + + ID3D11Texture2D *mSwizzleTexture; + ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h new file mode 100644 index 0000000000..590cb9f05a --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h @@ -0,0 +1,42 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexArray11.h: Defines the rx::VertexArray11 class which implements rx::VertexArrayImpl. + +#ifndef LIBGLESV2_RENDERER_VERTEXARRAY11_H_ +#define LIBGLESV2_RENDERER_VERTEXARRAY11_H_ + +#include "libGLESv2/renderer/VertexArrayImpl.h" +#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h" + +namespace rx +{ +class Renderer11; + +class VertexArray11 : public VertexArrayImpl +{ + public: + VertexArray11(rx::Renderer11 *renderer) + : VertexArrayImpl(), + mRenderer(renderer) + { + } + virtual ~VertexArray11() { } + + virtual void setElementArrayBuffer(const gl::Buffer *buffer) { } + virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) { } + virtual void setAttributeDivisor(size_t idx, GLuint divisor) { } + virtual void enableAttribute(size_t idx, bool enabledState) { } + + private: + DISALLOW_COPY_AND_ASSIGN(VertexArray11); + + rx::Renderer11 *mRenderer; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXARRAY11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp new file mode 100644 index 0000000000..2f47ec0a67 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp @@ -0,0 +1,223 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation. + +#include "libGLESv2/renderer/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" + +namespace rx +{ + +VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer) +{ + mBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; +} + +VertexBuffer11::~VertexBuffer11() +{ + SafeRelease(mBuffer); +} + +bool VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) +{ + SafeRelease(mBuffer); + + updateSerial(); + + if (size > 0) + { + ID3D11Device* dxDevice = mRenderer->getDevice(); + + D3D11_BUFFER_DESC bufferDesc; + bufferDesc.ByteWidth = size; + bufferDesc.Usage = D3D11_USAGE_DYNAMIC; + bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; + bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + bufferDesc.MiscFlags = 0; + bufferDesc.StructureByteStride = 0; + + HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); + if (FAILED(result)) + { + return false; + } + } + + mBufferSize = size; + mDynamicUsage = dynamicUsage; + return true; +} + +VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer)); + return static_cast(vetexBuffer); +} + +bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int offset) +{ + if (mBuffer) + { + gl::Buffer *buffer = attrib.buffer.get(); + int inputStride = ComputeVertexAttributeStride(attrib); + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Vertex buffer map failed with error 0x%08x", result); + return false; + } + + char* output = reinterpret_cast(mappedResource.pData) + offset; + + const char *input = NULL; + if (attrib.enabled) + { + if (buffer) + { + Buffer11 *storage = Buffer11::makeBuffer11(buffer->getImplementation()); + input = static_cast(storage->getData()) + static_cast(attrib.offset); + } + else + { + input = static_cast(attrib.pointer); + } + } + else + { + input = reinterpret_cast(currentValue.FloatValues); + } + + if (instances == 0 || attrib.divisor == 0) + { + input += inputStride * start; + } + + gl::VertexFormat vertexFormat(attrib, currentValue.Type); + 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; + } +} + +bool VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, + GLsizei instances, unsigned int *outSpaceRequired) const +{ + unsigned int elementCount = 0; + if (attrib.enabled) + { + if (instances == 0 || attrib.divisor == 0) + { + elementCount = count; + } + else + { + 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; + } + } + + gl::VertexFormat vertexFormat(attrib); + unsigned int elementSize = static_cast(gl_d3d11::GetVertexElementSize(vertexFormat)); + if (elementSize <= std::numeric_limits::max() / elementCount) + { + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * elementCount; + } + return true; + } + else + { + return false; + } + } + else + { + const unsigned int elementSize = 4; + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * 4; + } + return true; + } +} + +unsigned int VertexBuffer11::getBufferSize() const +{ + return mBufferSize; +} + +bool VertexBuffer11::setBufferSize(unsigned int size) +{ + if (size > mBufferSize) + { + return initialize(size, mDynamicUsage); + } + else + { + return true; + } +} + +bool VertexBuffer11::discard() +{ + if (mBuffer) + { + ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); + + D3D11_MAPPED_SUBRESOURCE mappedResource; + HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + if (FAILED(result)) + { + ERR("Vertex buffer map failed with error 0x%08x", result); + return false; + } + + dxContext->Unmap(mBuffer, 0); + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +ID3D11Buffer *VertexBuffer11::getBuffer() const +{ + return mBuffer; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h new file mode 100644 index 0000000000..c2a5aa7afd --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h @@ -0,0 +1,52 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexBuffer11.h: Defines the D3D11 VertexBuffer implementation. + +#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ +#define LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ + +#include "libGLESv2/renderer/d3d/VertexBuffer.h" + +namespace rx +{ +class Renderer11; + +class VertexBuffer11 : public VertexBuffer +{ + public: + explicit VertexBuffer11(rx::Renderer11 *const renderer); + virtual ~VertexBuffer11(); + + virtual bool initialize(unsigned int size, bool dynamicUsage); + + static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer); + + virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, 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 unsigned int getBufferSize() const; + virtual bool setBufferSize(unsigned int size); + virtual bool discard(); + + ID3D11Buffer *getBuffer() const; + + private: + DISALLOW_COPY_AND_ASSIGN(VertexBuffer11); + + rx::Renderer11 *const mRenderer; + + ID3D11Buffer *mBuffer; + unsigned int mBufferSize; + bool mDynamicUsage; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp new file mode 100644 index 0000000000..c991fd4991 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp @@ -0,0 +1,1458 @@ +#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 +// found in the LICENSE file. +// + +// formatutils11.cpp: Queries for GL image formats and their translations to D3D11 +// formats. + +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "libGLESv2/renderer/generatemip.h" +#include "libGLESv2/renderer/loadimage.h" +#include "libGLESv2/renderer/copyimage.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/copyvertex.h" + +namespace rx +{ + +struct D3D11FormatInfo +{ + 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) + { } +}; + +// 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; + +static D3D11ES3FormatMap BuildD3D11FormatMap() +{ + D3D11ES3FormatMap 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))); + + // 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))); + + // 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 ))); + + // 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 ))); + + // 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 ))); + + // 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))); + + // 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))); + + // 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))); + + // 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))); + + return map; +} + +static bool GetD3D11FormatInfo(GLenum internalFormat, D3D11FormatInfo *outFormatInfo) +{ + static const D3D11ES3FormatMap formatMap = BuildD3D11FormatMap(); + D3D11ES3FormatMap::const_iterator iter = formatMap.find(internalFormat); + if (iter != formatMap.end()) + { + if (outFormatInfo) + { + *outFormatInfo = iter->second; + } + return true; + } + else + { + return false; + } +} + +// 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; + +static void UnimplementedLoadFunction(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + UNIMPLEMENTED(); +} + +static void UnreachableLoadFunction(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + UNREACHABLE(); +} + +// A helper function to insert data into the D3D11LoadFunctionMap with fewer characters. +static inline void insertLoadFunction(D3D11LoadFunctionMap *map, GLenum internalFormat, GLenum type, + LoadImageFunction loadFunc) +{ + map->insert(D3D11LoadFunctionPair(InternalFormatTypePair(internalFormat, type), loadFunc)); +} + +D3D11LoadFunctionMap buildD3D11LoadFunctionMap() +{ + D3D11LoadFunctionMap map; + + // | Internal format | Type | Load function | + insertLoadFunction(&map, GL_RGBA8, GL_UNSIGNED_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_RGBA4, GL_UNSIGNED_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_SRGB8_ALPHA8, GL_UNSIGNED_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_RGBA8_SNORM, GL_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_RGBA4, GL_UNSIGNED_SHORT_4_4_4_4, LoadRGBA4ToRGBA8 ); + insertLoadFunction(&map, GL_RGB10_A2, GL_UNSIGNED_INT_2_10_10_10_REV, LoadToNative ); + insertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_SHORT_5_5_5_1, LoadRGB5A1ToRGBA8 ); + insertLoadFunction(&map, GL_RGB5_A1, GL_UNSIGNED_INT_2_10_10_10_REV, LoadRGB10A2ToRGBA8 ); + insertLoadFunction(&map, GL_RGBA16F, GL_HALF_FLOAT, LoadToNative ); + insertLoadFunction(&map, GL_RGBA16F, GL_HALF_FLOAT_OES, LoadToNative ); + insertLoadFunction(&map, GL_RGBA32F, GL_FLOAT, LoadToNative ); + insertLoadFunction(&map, GL_RGBA16F, GL_FLOAT, Load32FTo16F<4> ); + insertLoadFunction(&map, GL_RGBA8UI, GL_UNSIGNED_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_RGBA8I, GL_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_RGBA16UI, GL_UNSIGNED_SHORT, LoadToNative ); + insertLoadFunction(&map, GL_RGBA16I, GL_SHORT, LoadToNative ); + insertLoadFunction(&map, GL_RGBA32UI, GL_UNSIGNED_INT, LoadToNative ); + insertLoadFunction(&map, GL_RGBA32I, GL_INT, LoadToNative ); + insertLoadFunction(&map, GL_RGB10_A2UI, GL_UNSIGNED_INT_2_10_10_10_REV, LoadToNative ); + insertLoadFunction(&map, GL_RGB8, GL_UNSIGNED_BYTE, LoadToNative3To4 ); + insertLoadFunction(&map, GL_RGB565, GL_UNSIGNED_BYTE, LoadToNative3To4 ); + insertLoadFunction(&map, GL_SRGB8, GL_UNSIGNED_BYTE, LoadToNative3To4 ); + insertLoadFunction(&map, GL_RGB8_SNORM, GL_BYTE, LoadToNative3To4 ); + insertLoadFunction(&map, GL_RGB565, GL_UNSIGNED_SHORT_5_6_5, LoadR5G6B5ToRGBA8 ); + insertLoadFunction(&map, GL_R11F_G11F_B10F, GL_UNSIGNED_INT_10F_11F_11F_REV, LoadToNative ); + insertLoadFunction(&map, GL_RGB9_E5, GL_UNSIGNED_INT_5_9_9_9_REV, LoadToNative ); + insertLoadFunction(&map, GL_RGB16F, GL_HALF_FLOAT, LoadToNative3To4); + insertLoadFunction(&map, GL_RGB16F, GL_HALF_FLOAT_OES, LoadToNative3To4); + insertLoadFunction(&map, GL_R11F_G11F_B10F, GL_HALF_FLOAT, LoadRGB16FToRG11B10F ); + insertLoadFunction(&map, GL_R11F_G11F_B10F, GL_HALF_FLOAT_OES, LoadRGB16FToRG11B10F ); + insertLoadFunction(&map, GL_RGB9_E5, GL_HALF_FLOAT, LoadRGB16FToRGB9E5 ); + insertLoadFunction(&map, GL_RGB9_E5, GL_HALF_FLOAT_OES, LoadRGB16FToRGB9E5 ); + insertLoadFunction(&map, GL_RGB32F, GL_FLOAT, LoadToNative3To4); + insertLoadFunction(&map, GL_RGB16F, GL_FLOAT, LoadRGB32FToRGBA16F ); + insertLoadFunction(&map, GL_R11F_G11F_B10F, GL_FLOAT, LoadRGB32FToRG11B10F ); + insertLoadFunction(&map, GL_RGB9_E5, GL_FLOAT, LoadRGB32FToRGB9E5 ); + insertLoadFunction(&map, GL_RGB8UI, GL_UNSIGNED_BYTE, LoadToNative3To4 ); + insertLoadFunction(&map, GL_RGB8I, GL_BYTE, LoadToNative3To4 ); + insertLoadFunction(&map, GL_RGB16UI, GL_UNSIGNED_SHORT, LoadToNative3To4 ); + insertLoadFunction(&map, GL_RGB16I, GL_SHORT, LoadToNative3To4 ); + insertLoadFunction(&map, GL_RGB32UI, GL_UNSIGNED_INT, LoadToNative3To4 ); + insertLoadFunction(&map, GL_RGB32I, GL_INT, LoadToNative3To4 ); + insertLoadFunction(&map, GL_RG8, GL_UNSIGNED_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_RG8_SNORM, GL_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_RG16F, GL_HALF_FLOAT, LoadToNative ); + insertLoadFunction(&map, GL_RG16F, GL_HALF_FLOAT_OES, LoadToNative ); + insertLoadFunction(&map, GL_RG32F, GL_FLOAT, LoadToNative ); + insertLoadFunction(&map, GL_RG16F, GL_FLOAT, Load32FTo16F<2> ); + insertLoadFunction(&map, GL_RG8UI, GL_UNSIGNED_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_RG8I, GL_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_RG16UI, GL_UNSIGNED_SHORT, LoadToNative ); + insertLoadFunction(&map, GL_RG16I, GL_SHORT, LoadToNative ); + insertLoadFunction(&map, GL_RG32UI, GL_UNSIGNED_INT, LoadToNative ); + insertLoadFunction(&map, GL_RG32I, GL_INT, LoadToNative ); + insertLoadFunction(&map, GL_R8, GL_UNSIGNED_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_R8_SNORM, GL_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_R16F, GL_HALF_FLOAT, LoadToNative ); + insertLoadFunction(&map, GL_R16F, GL_HALF_FLOAT_OES, LoadToNative ); + insertLoadFunction(&map, GL_R32F, GL_FLOAT, LoadToNative ); + insertLoadFunction(&map, GL_R16F, GL_FLOAT, Load32FTo16F<1> ); + insertLoadFunction(&map, GL_R8UI, GL_UNSIGNED_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_R8I, GL_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_R16UI, GL_UNSIGNED_SHORT, LoadToNative ); + insertLoadFunction(&map, GL_R16I, GL_SHORT, LoadToNative ); + insertLoadFunction(&map, GL_R32UI, GL_UNSIGNED_INT, LoadToNative ); + insertLoadFunction(&map, GL_R32I, GL_INT, LoadToNative ); + insertLoadFunction(&map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_SHORT, LoadToNative ); + insertLoadFunction(&map, GL_DEPTH_COMPONENT24, GL_UNSIGNED_INT, LoadR32ToR24G8 ); + insertLoadFunction(&map, GL_DEPTH_COMPONENT16, GL_UNSIGNED_INT, LoadR32ToR16 ); + insertLoadFunction(&map, GL_DEPTH_COMPONENT32F, GL_FLOAT, LoadToNative ); + insertLoadFunction(&map, GL_DEPTH24_STENCIL8, GL_UNSIGNED_INT_24_8, LoadR32ToR24G8 ); + insertLoadFunction(&map, GL_DEPTH32F_STENCIL8, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, LoadToNative ); + + // Unsized formats + // Load functions are unreachable because they are converted to sized internal formats based on + // the format and type before loading takes place. + insertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + insertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, UnreachableLoadFunction ); + insertLoadFunction(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, UnreachableLoadFunction ); + insertLoadFunction(&map, GL_RGB, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + insertLoadFunction(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, UnreachableLoadFunction ); + insertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + insertLoadFunction(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + insertLoadFunction(&map, GL_ALPHA, GL_UNSIGNED_BYTE, UnreachableLoadFunction ); + + // From GL_OES_texture_float + insertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, LoadLA32FToRGBA32F ); + insertLoadFunction(&map, GL_LUMINANCE, GL_FLOAT, LoadL32FToRGBA32F ); + insertLoadFunction(&map, GL_ALPHA, GL_FLOAT, LoadA32FToRGBA32F ); + + // From GL_OES_texture_half_float + insertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, LoadLA16FToRGBA16F ); + insertLoadFunction(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, LoadLA16FToRGBA16F ); + insertLoadFunction(&map, GL_LUMINANCE, GL_HALF_FLOAT, LoadL16FToRGBA16F ); + insertLoadFunction(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, LoadL16FToRGBA16F ); + insertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT, LoadA16FToRGBA16F ); + insertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F ); + + // From GL_EXT_texture_storage + insertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, 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 ); + + // From GL_ANGLE_depth_texture + insertLoadFunction(&map, GL_DEPTH_COMPONENT32_OES, GL_UNSIGNED_INT, LoadR32ToR24G8 ); + + // From GL_EXT_texture_format_BGRA8888 + insertLoadFunction(&map, GL_BGRA8_EXT, GL_UNSIGNED_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_BGRA4_ANGLEX, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, LoadRGBA4ToRGBA8 ); + insertLoadFunction(&map, GL_BGRA4_ANGLEX, GL_UNSIGNED_BYTE, LoadToNative ); + insertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, LoadRGB5A1ToRGBA8 ); + insertLoadFunction(&map, GL_BGR5_A1_ANGLEX, GL_UNSIGNED_BYTE, LoadToNative ); + + // Compressed formats + // From ES 3.0.1 spec, table 3.16 + // | Internal format | Type | Load function | + insertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_SIGNED_R11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_RG11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_SIGNED_RG11_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_RGB8_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_SRGB8_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + insertLoadFunction(&map, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_UNSIGNED_BYTE, UnimplementedLoadFunction ); + + // From GL_EXT_texture_compression_dxt1 + insertLoadFunction(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 8>); + insertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 8>); + + // From GL_ANGLE_texture_compression_dxt3 + insertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>); + + // From GL_ANGLE_texture_compression_dxt5 + insertLoadFunction(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, LoadCompressedToNative<4, 4, 16>); + + return map; +} + +// A map to determine the pixel size and mipmap generation function of a given DXGI format +struct DXGIFormatInfo +{ + GLuint mPixelBits; + GLuint mBlockWidth; + GLuint mBlockHeight; + GLenum mComponentType; + + MipGenerationFunction mMipGenerationFunction; + ColorReadFunction mColorReadFunction; + + DXGIFormatInfo() + : mPixelBits(0), mBlockWidth(0), mBlockHeight(0), mComponentType(GL_NONE), mMipGenerationFunction(NULL), + mColorReadFunction(NULL) + { } + + 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) + { } +}; + +typedef std::map DXGIFormatInfoMap; + +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 DXGIFormatInfoMap BuildDXGIFormatInfoMap() +{ + DXGIFormatInfoMap map; + + // | DXGI format |S |W |H |Component Type | Mip generation function | Color read function + AddDXGIFormat(&map, DXGI_FORMAT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL); + + AddDXGIFormat(&map, DXGI_FORMAT_A8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8_UNORM, 8, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R8_SNORM, 8, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R8_UINT, 8, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_UINT, 16, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_UINT, 96, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UINT, 64, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_UINT, 128, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R8_SINT, 8, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16_SINT, 16, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8_SINT, 16, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32_SINT, 64, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_SINT, 96, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R8G8B8A8_SINT, 32, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SINT, 64, 1, 1, GL_INT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_SINT, 128, 1, 1, GL_INT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R10G10B10A2_UINT, 32, 1, 1, GL_UNSIGNED_INT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R16_FLOAT, 16, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32_FLOAT, 64, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32_FLOAT, 96, 1, 1, GL_FLOAT, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 128, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + AddDXGIFormat(&map, DXGI_FORMAT_R11G11B10_FLOAT, 32, 1, 1, GL_FLOAT, GenerateMip, ReadColor); + + AddDXGIFormat(&map, DXGI_FORMAT_R16_TYPELESS, 16, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_D16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R24G8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_D24_UNORM_S8_UINT, 32, 1, 1, GL_UNSIGNED_INT, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R32G8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS, 64, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT_S8X24_UINT, 64, 1, 1, GL_UNSIGNED_INT, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R32_TYPELESS, 32, 1, 1, GL_NONE, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_D32_FLOAT, 32, 1, 1, GL_FLOAT, NULL, NULL); + + AddDXGIFormat(&map, DXGI_FORMAT_BC1_UNORM, 64, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_BC2_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_BC3_UNORM, 128, 4, 4, GL_UNSIGNED_NORMALIZED, NULL, NULL); + + // Useful formats for vertex buffers + AddDXGIFormat(&map, DXGI_FORMAT_R16_UNORM, 16, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16_SNORM, 16, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_UNORM, 32, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16_SNORM, 32, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_UNORM, 64, 1, 1, GL_UNSIGNED_NORMALIZED, NULL, NULL); + AddDXGIFormat(&map, DXGI_FORMAT_R16G16B16A16_SNORM, 64, 1, 1, GL_SIGNED_NORMALIZED, NULL, NULL); + + return map; +} + +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() +{ + 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; + } + else + { + return false; + } +} + +struct SwizzleSizeType +{ + unsigned int mMaxComponentSize; + GLenum mComponentType; + + SwizzleSizeType() + : mMaxComponentSize(0), mComponentType(GL_NONE) + { } + + SwizzleSizeType(unsigned int maxComponentSize, GLenum componentType) + : mMaxComponentSize(maxComponentSize), mComponentType(componentType) + { } + + bool operator<(const SwizzleSizeType& other) const + { + return (mMaxComponentSize != other.mMaxComponentSize) ? (mMaxComponentSize < other.mMaxComponentSize) + : (mComponentType < other.mComponentType); + } +}; + +struct SwizzleFormatInfo +{ + DXGI_FORMAT mTexFormat; + DXGI_FORMAT mSRVFormat; + DXGI_FORMAT mRTVFormat; + + SwizzleFormatInfo() + : mTexFormat(DXGI_FORMAT_UNKNOWN), mSRVFormat(DXGI_FORMAT_UNKNOWN), mRTVFormat(DXGI_FORMAT_UNKNOWN) + { } + + SwizzleFormatInfo(DXGI_FORMAT texFormat, DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat) + : mTexFormat(texFormat), mSRVFormat(srvFormat), mRTVFormat(rtvFormat) + { } +}; + +typedef std::map SwizzleInfoMap; +typedef std::pair SwizzleInfoPair; + +static SwizzleInfoMap BuildSwizzleInfoMap() +{ + SwizzleInfoMap map; + + map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM, DXGI_FORMAT_R16G16B16A16_UNORM))); + map.insert(SwizzleInfoPair(SwizzleSizeType(24, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); + map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_NORMALIZED), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); + + map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_SIGNED_NORMALIZED ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_SNORM ))); + + map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_FLOAT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT, DXGI_FORMAT_R16G16B16A16_FLOAT))); + map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_FLOAT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT))); + + map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_UINT ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT, DXGI_FORMAT_R16G16B16A16_UINT ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_UNSIGNED_INT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT, DXGI_FORMAT_R32G32B32A32_UINT ))); + + map.insert(SwizzleInfoPair(SwizzleSizeType( 8, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_SINT ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(16, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT, DXGI_FORMAT_R16G16B16A16_SINT ))); + map.insert(SwizzleInfoPair(SwizzleSizeType(32, GL_INT ), SwizzleFormatInfo(DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT, DXGI_FORMAT_R32G32B32A32_SINT ))); + + return map; +} +typedef std::pair InternalFormatInitializerPair; +typedef std::map InternalFormatInitializerMap; + +static InternalFormatInitializerMap BuildInternalFormatInitializerMap() +{ + InternalFormatInitializerMap map; + + map.insert(InternalFormatInitializerPair(GL_RGB8, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB565, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_SRGB8, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB16F, Initialize4ComponentData)); + map.insert(InternalFormatInitializerPair(GL_RGB32F, Initialize4ComponentData)); + map.insert(InternalFormatInitializerPair(GL_RGB8UI, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB8I, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB16UI, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB16I, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB32UI, Initialize4ComponentData )); + map.insert(InternalFormatInitializerPair(GL_RGB32I, Initialize4ComponentData )); + + return map; +} + +static const SwizzleInfoMap &GetSwizzleInfoMap() +{ + static const SwizzleInfoMap map = BuildSwizzleInfoMap(); + return map; +} + +static const SwizzleFormatInfo GetSwizzleFormatInfo(GLenum internalFormat) +{ + // Get the maximum sized component + unsigned int maxBits = 1; + + 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)); + } + + maxBits = roundUp(maxBits, 8U); + + GLenum componentType = gl::GetComponentType(internalFormat); + + const SwizzleInfoMap &map = GetSwizzleInfoMap(); + SwizzleInfoMap::const_iterator iter = map.find(SwizzleSizeType(maxBits, componentType)); + + if (iter != map.end()) + { + return iter->second; + } + else + { + UNREACHABLE(); + static const SwizzleFormatInfo defaultFormatInfo; + return defaultFormatInfo; + } +} + +static const InternalFormatInitializerMap &GetInternalFormatInitializerMap() +{ + static const InternalFormatInitializerMap map = BuildInternalFormatInitializerMap(); + return map; +} + +namespace d3d11 +{ + +MipGenerationFunction GetMipGenerationFunction(DXGI_FORMAT format) +{ + DXGIFormatInfo formatInfo; + if (GetDXGIFormatInfo(format, &formatInfo)) + { + return formatInfo.mMipGenerationFunction; + } + else + { + UNREACHABLE(); + return NULL; + } +} + +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; + } +} + +GLuint GetFormatPixelBytes(DXGI_FORMAT format) +{ + DXGIFormatInfo dxgiFormatInfo; + if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) + { + return dxgiFormatInfo.mPixelBits / 8; + } + else + { + UNREACHABLE(); + return 0; + } +} + +GLuint GetBlockWidth(DXGI_FORMAT format) +{ + DXGIFormatInfo dxgiFormatInfo; + if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) + { + return dxgiFormatInfo.mBlockWidth; + } + else + { + UNREACHABLE(); + return 0; + } +} + +GLuint GetBlockHeight(DXGI_FORMAT format) +{ + DXGIFormatInfo dxgiFormatInfo; + if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) + { + return dxgiFormatInfo.mBlockHeight; + } + else + { + UNREACHABLE(); + return 0; + } +} + +GLenum GetComponentType(DXGI_FORMAT format) +{ + DXGIFormatInfo dxgiFormatInfo; + if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) + { + return dxgiFormatInfo.mComponentType; + } + else + { + UNREACHABLE(); + return GL_NONE; + } +} + +GLuint GetDepthBits(DXGI_FORMAT format) +{ + 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; + } +} + +GLuint GetDepthOffset(DXGI_FORMAT format) +{ + DXGIDepthStencilInfo dxgiDSInfo; + if (GetDepthStencilInfo(format, &dxgiDSInfo)) + { + return dxgiDSInfo.mDepthOffset; + } + else + { + // Since the depth stencil info map does not contain all used DXGI formats, + // we should not assert that the format exists + return 0; + } +} + +GLuint GetStencilBits(DXGI_FORMAT format) +{ + DXGIDepthStencilInfo dxgiDSInfo; + if (GetDepthStencilInfo(format, &dxgiDSInfo)) + { + return dxgiDSInfo.mStencilBits; + } + else + { + // Since the depth stencil info map does not contain all used DXGI formats, + // we should not assert that the format exists + return 0; + } +} + +GLuint GetStencilOffset(DXGI_FORMAT format) +{ + DXGIDepthStencilInfo dxgiDSInfo; + if (GetDepthStencilInfo(format, &dxgiDSInfo)) + { + 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; + } +} + +void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) +{ + DXGIFormatInfo dxgiFormatInfo; + if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) + { + int upsampleCount = 0; + + GLsizei blockWidth = dxgiFormatInfo.mBlockWidth; + GLsizei blockHeight = dxgiFormatInfo.mBlockHeight; + + // 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; + } + else + { + UNREACHABLE(); + } +} + +const DXGIFormatSet &GetAllUsedDXGIFormats() +{ + static DXGIFormatSet formatSet = BuildAllDXGIFormatSet(); + return formatSet; +} + +ColorReadFunction GetColorReadFunction(DXGI_FORMAT format) +{ + DXGIFormatInfo dxgiFormatInfo; + if (GetDXGIFormatInfo(format, &dxgiFormatInfo)) + { + return dxgiFormatInfo.mColorReadFunction; + } + else + { + UNREACHABLE(); + return NULL; + } +} + +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; +} + +} + +namespace gl_d3d11 +{ + +DXGI_FORMAT GetTexFormat(GLenum internalFormat) +{ + D3D11FormatInfo d3d11FormatInfo; + if (GetD3D11FormatInfo(internalFormat, &d3d11FormatInfo)) + { + return d3d11FormatInfo.mTexFormat; + } + else + { + UNREACHABLE(); + return DXGI_FORMAT_UNKNOWN; + } +} + +DXGI_FORMAT GetSRVFormat(GLenum internalFormat) +{ + D3D11FormatInfo d3d11FormatInfo; + if (GetD3D11FormatInfo(internalFormat, &d3d11FormatInfo)) + { + return d3d11FormatInfo.mSRVFormat; + } + else + { + UNREACHABLE(); + return DXGI_FORMAT_UNKNOWN; + } +} + +DXGI_FORMAT GetRTVFormat(GLenum internalFormat) +{ + D3D11FormatInfo d3d11FormatInfo; + if (GetD3D11FormatInfo(internalFormat, &d3d11FormatInfo)) + { + return d3d11FormatInfo.mRTVFormat; + } + else + { + UNREACHABLE(); + return DXGI_FORMAT_UNKNOWN; + } +} + +DXGI_FORMAT GetDSVFormat(GLenum internalFormat) +{ + D3D11FormatInfo d3d11FormatInfo; + if (GetD3D11FormatInfo(internalFormat, &d3d11FormatInfo)) + { + return d3d11FormatInfo.mDSVFormat; + } + else + { + return DXGI_FORMAT_UNKNOWN; + } +} + +// 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); + + return targetFormat; +} + +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); + } +} + +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); + } +} + +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); + } +} + +bool RequiresTextureDataInitialization(GLint internalFormat) +{ + const InternalFormatInitializerMap &map = GetInternalFormatInitializerMap(); + return map.find(internalFormat) != map.end(); +} + +InitializeTextureDataFunction GetTextureDataInitializationFunction(GLint internalFormat) +{ + const InternalFormatInitializerMap &map = GetInternalFormatInitializerMap(); + InternalFormatInitializerMap::const_iterator iter = map.find(internalFormat); + if (iter != map.end()) + { + return iter->second; + } + else + { + UNREACHABLE(); + return NULL; + } +} + +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; + +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))); +} + +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))); +} + +static D3D11VertexFormatInfoMap BuildD3D11VertexFormatInfoMap() +{ + D3D11VertexFormatInfoMap map; + + // TODO: column legend + + // + // Float formats + // + + // GL_BYTE -- un-normalized + addVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, ©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); + + // 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); + + // 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); + + // 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); + + // 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); + + // 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); + + // 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); + + // 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); + + // 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); + + // 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); + + // 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); + + // 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); + + // 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>); + + // 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); + + // 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); + + // 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); + + // 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); + + // + // 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); + + // 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); + + // 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); + + // 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); + + // 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); + + // 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); + + // 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); + + // 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); + + return map; +} + +static bool GetD3D11VertexFormatInfo(const gl::VertexFormat &vertexFormat, D3D11VertexFormatInfo *outVertexFormatInfo) +{ + 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; + } +} + +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h new file mode 100644 index 0000000000..d77fccfe9c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h @@ -0,0 +1,79 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// formatutils11.h: Queries for GL image formats and their translations to D3D11 +// formats. + +#ifndef LIBGLESV2_RENDERER_FORMATUTILS11_H_ +#define LIBGLESV2_RENDERER_FORMATUTILS11_H_ + +#include "libGLESv2/formatutils.h" + +namespace rx +{ + +class Renderer; + +namespace d3d11 +{ + +typedef std::set DXGIFormatSet; + +MipGenerationFunction GetMipGenerationFunction(DXGI_FORMAT format); +LoadImageFunction GetImageLoadFunction(GLenum internalFormat, GLenum type); + +GLuint GetFormatPixelBytes(DXGI_FORMAT format); +GLuint GetBlockWidth(DXGI_FORMAT format); +GLuint GetBlockHeight(DXGI_FORMAT format); +GLenum GetComponentType(DXGI_FORMAT format); + +GLuint GetDepthBits(DXGI_FORMAT format); +GLuint GetDepthOffset(DXGI_FORMAT format); +GLuint GetStencilBits(DXGI_FORMAT format); +GLuint GetStencilOffset(DXGI_FORMAT format); + +void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); + +const DXGIFormatSet &GetAllUsedDXGIFormats(); + +ColorReadFunction GetColorReadFunction(DXGI_FORMAT format); +ColorCopyFunction GetFastCopyFunction(DXGI_FORMAT sourceFormat, GLenum destFormat, GLenum destType); + +} + +namespace gl_d3d11 +{ + +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); + +bool RequiresTextureDataInitialization(GLint internalFormat); +InitializeTextureDataFunction GetTextureDataInitializationFunction(GLint internalFormat); + +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); + +} + +namespace d3d11_gl +{ + +GLenum GetInternalFormat(DXGI_FORMAT format); + +} + +} + +#endif // LIBGLESV2_RENDERER_FORMATUTILS11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp new file mode 100644 index 0000000000..d3d135fe5b --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp @@ -0,0 +1,634 @@ +#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 +// found in the LICENSE file. +// + +// renderer11_utils.cpp: Conversion functions and other utility routines +// specific to the D3D11 renderer. + +#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h" +#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h" +#include "common/debug.h" + +namespace rx +{ + +namespace gl_d3d11 +{ + +D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha) +{ + D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO; + + switch (glBlend) + { + case GL_ZERO: d3dBlend = D3D11_BLEND_ZERO; break; + case GL_ONE: d3dBlend = D3D11_BLEND_ONE; break; + case GL_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR); break; + case GL_ONE_MINUS_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR); break; + case GL_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR); break; + case GL_ONE_MINUS_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR); break; + case GL_SRC_ALPHA: d3dBlend = D3D11_BLEND_SRC_ALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3D11_BLEND_INV_SRC_ALPHA; break; + case GL_DST_ALPHA: d3dBlend = D3D11_BLEND_DEST_ALPHA; break; + case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3D11_BLEND_INV_DEST_ALPHA; break; + case GL_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break; + case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break; + case GL_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break; + case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break; + case GL_SRC_ALPHA_SATURATE: d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT; break; + default: UNREACHABLE(); + } + + return d3dBlend; +} + +D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp) +{ + D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD; + + switch (glBlendOp) + { + case GL_FUNC_ADD: d3dBlendOp = D3D11_BLEND_OP_ADD; break; + case GL_FUNC_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_SUBTRACT; break; + case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT; break; + case GL_MIN: d3dBlendOp = D3D11_BLEND_OP_MIN; break; + case GL_MAX: d3dBlendOp = D3D11_BLEND_OP_MAX; break; + default: UNREACHABLE(); + } + + return d3dBlendOp; +} + +UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha) +{ + UINT8 mask = 0; + if (red) + { + mask |= D3D11_COLOR_WRITE_ENABLE_RED; + } + if (green) + { + mask |= D3D11_COLOR_WRITE_ENABLE_GREEN; + } + if (blue) + { + mask |= D3D11_COLOR_WRITE_ENABLE_BLUE; + } + if (alpha) + { + mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA; + } + return mask; +} + +D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode) +{ + D3D11_CULL_MODE cull = D3D11_CULL_NONE; + + if (cullEnabled) + { + switch (cullMode) + { + case GL_FRONT: cull = D3D11_CULL_FRONT; break; + case GL_BACK: cull = D3D11_CULL_BACK; break; + case GL_FRONT_AND_BACK: cull = D3D11_CULL_NONE; break; + default: UNREACHABLE(); + } + } + else + { + cull = D3D11_CULL_NONE; + } + + return cull; +} + +D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison) +{ + D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER; + switch (comparison) + { + case GL_NEVER: d3dComp = D3D11_COMPARISON_NEVER; break; + case GL_ALWAYS: d3dComp = D3D11_COMPARISON_ALWAYS; break; + case GL_LESS: d3dComp = D3D11_COMPARISON_LESS; break; + case GL_LEQUAL: d3dComp = D3D11_COMPARISON_LESS_EQUAL; break; + case GL_EQUAL: d3dComp = D3D11_COMPARISON_EQUAL; break; + case GL_GREATER: d3dComp = D3D11_COMPARISON_GREATER; break; + case GL_GEQUAL: d3dComp = D3D11_COMPARISON_GREATER_EQUAL; break; + case GL_NOTEQUAL: d3dComp = D3D11_COMPARISON_NOT_EQUAL; break; + default: UNREACHABLE(); + } + + return d3dComp; +} + +D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled) +{ + return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; +} + +UINT8 ConvertStencilMask(GLuint stencilmask) +{ + return static_cast(stencilmask); +} + +D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp) +{ + D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP; + + switch (stencilOp) + { + case GL_ZERO: d3dStencilOp = D3D11_STENCIL_OP_ZERO; break; + case GL_KEEP: d3dStencilOp = D3D11_STENCIL_OP_KEEP; break; + case GL_REPLACE: d3dStencilOp = D3D11_STENCIL_OP_REPLACE; break; + case GL_INCR: d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT; break; + case GL_DECR: d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT; break; + case GL_INVERT: d3dStencilOp = D3D11_STENCIL_OP_INVERT; break; + case GL_INCR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_INCR; break; + case GL_DECR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_DECR; break; + default: UNREACHABLE(); + } + + return d3dStencilOp; +} + +D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy, GLenum comparisonMode) +{ + bool comparison = comparisonMode != GL_NONE; + + if (maxAnisotropy > 1.0f) + { + return D3D11_ENCODE_ANISOTROPIC_FILTER(static_cast(comparison)); + } + else + { + D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT; + D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT; + switch (minFilter) + { + case GL_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break; + case GL_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break; + case GL_NEAREST_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break; + case GL_LINEAR_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break; + case GL_NEAREST_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_LINEAR; break; + case GL_LINEAR_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_LINEAR; break; + default: UNREACHABLE(); + } + + D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT; + switch (magFilter) + { + case GL_NEAREST: dxMag = D3D11_FILTER_TYPE_POINT; break; + case GL_LINEAR: dxMag = D3D11_FILTER_TYPE_LINEAR; break; + default: UNREACHABLE(); + } + + return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip, static_cast(comparison)); + } +} + +D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap) +{ + switch (wrap) + { + case GL_REPEAT: return D3D11_TEXTURE_ADDRESS_WRAP; + case GL_CLAMP_TO_EDGE: return D3D11_TEXTURE_ADDRESS_CLAMP; + case GL_MIRRORED_REPEAT: return D3D11_TEXTURE_ADDRESS_MIRROR; + default: UNREACHABLE(); + } + + return D3D11_TEXTURE_ADDRESS_WRAP; +} + +D3D11_QUERY ConvertQueryType(GLenum queryType) +{ + switch (queryType) + { + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: return D3D11_QUERY_OCCLUSION; + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: return D3D11_QUERY_SO_STATISTICS; + default: UNREACHABLE(); return D3D11_QUERY_EVENT; + } +} + +} + + +namespace d3d11_gl +{ + +static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, ID3D11Device *device) +{ + gl::TextureCaps textureCaps; + + 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); + + UINT formatSupport; + if (SUCCEEDED(device->CheckFormatSupport(textureFormat, &formatSupport))) + { + if (gl::GetDepthBits(internalFormat) > 0 || gl::GetStencilBits(internalFormat) > 0) + { + textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0); + } + else + { + textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0) && + ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE) != 0) && + ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE3D) != 0); + } + } + + if (SUCCEEDED(device->CheckFormatSupport(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)) && + qualityCount > 0) + { + textureCaps.sampleCounts.insert(sampleCount); + } + } + } + + textureCaps.filterable = SUCCEEDED(device->CheckFormatSupport(srvFormat, &formatSupport)) && + ((formatSupport & D3D11_FORMAT_SUPPORT_SHADER_SAMPLE)) != 0; + textureCaps.renderable = (SUCCEEDED(device->CheckFormatSupport(rtvFormat, &formatSupport)) && + ((formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) != 0) || + (SUCCEEDED(device->CheckFormatSupport(dsvFormat, &formatSupport)) && + ((formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL) != 0)); + + return textureCaps; +} + +static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_MAX_MAXANISOTROPY; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: return 16; + + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; + + default: UNREACHABLE(); return 0; + } +} + +static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return true; + + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: return true; + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel) +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateQuery + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return true; + + default: UNREACHABLE(); return false; + } +} + +static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel) +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: return true; + + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel) +{ + // http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that shader model + // ps_2_x is required for the ddx (and other derivative functions). + + // http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx states that feature level + // 9.3 supports shader model ps_2_x. + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + case D3D_FEATURE_LEVEL_9_3: return true; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return false; + + default: UNREACHABLE(); return false; + } +} + +static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel) +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout + + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + 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_9_3: return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURECUBE_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return 0; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + case D3D_FEATURE_LEVEL_9_3: + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION; + + default: UNREACHABLE(); return 0; + } +} + +static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel) +{ + switch (featureLevel) + { + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX; + + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: return D3D10_VIEWPORT_BOUNDS_MAX; + + // No constants for D3D9 viewport size limits, use the maximum texture sizes + case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; + case D3D_FEATURE_LEVEL_9_2: + case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; + + default: UNREACHABLE(); return 0; + } +} + +void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions) +{ + 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); + } + + D3D_FEATURE_LEVEL featureLevel = device->GetFeatureLevel(); + + // GL core feature limits + caps->maxElementIndex = static_cast(std::numeric_limits::max()); + caps->max3DTextureSize = GetMaximum3DTextureSize(featureLevel); + caps->max2DTextureSize = GetMaximum2DTextureSize(featureLevel); + caps->maxCubeMapTextureSize = GetMaximumCubeMapTextureSize(featureLevel); + caps->maxArrayTextureLayers = GetMaximum2DTextureArraySize(featureLevel); + + // Unimplemented, set to minimum required + caps->maxLODBias = 2.0f; + + // No specific limits on render target size, maximum 2D texture size is equivalent + caps->maxRenderbufferSize = caps->max2DTextureSize; + + // Maximum draw buffers and color attachments are the same, max color attachments could eventually be + // increased to 16 + caps->maxDrawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel); + caps->maxColorAttachments = GetMaximumSimultaneousRenderTargets(featureLevel); + + // D3D11 has the same limit for viewport width and height + caps->maxViewportWidth = GetMaximumViewportSize(featureLevel); + caps->maxViewportHeight = caps->maxViewportWidth; + + // Choose a reasonable maximum, enforced in the shader. + caps->minAliasedPointSize = 1.0f; + caps->maxAliasedPointSize = 1024.0f; + + // Wide lines not supported + caps->minAliasedLineWidth = 1.0f; + caps->maxAliasedLineWidth = 1.0f; + + // GL extension support + extensions->setTextureExtensionSupport(*textureCapsMap); + extensions->elementIndexUint = true; + extensions->packedDepthStencil = true; + extensions->getProgramBinary = true; + extensions->rgb8rgba8 = true; + extensions->readFormatBGRA = true; + extensions->pixelBufferObject = true; + extensions->mapBuffer = true; + extensions->mapBufferRange = true; + extensions->textureNPOT = GetNPOTTextureSupport(featureLevel); + extensions->drawBuffers = GetMaximumSimultaneousRenderTargets(featureLevel) > 1; + extensions->textureStorage = true; + extensions->textureFilterAnisotropic = true; + extensions->maxTextureAnisotropy = GetMaximumAnisotropy(featureLevel); + extensions->occlusionQueryBoolean = GetOcclusionQuerySupport(featureLevel); + extensions->fence = GetEventQuerySupport(featureLevel); + extensions->timerQuery = false; // Unimplemented + extensions->robustness = true; + extensions->blendMinMax = true; + extensions->framebufferBlit = true; + extensions->framebufferMultisample = true; + extensions->instancedArrays = GetInstancingSupport(featureLevel); + extensions->packReverseRowOrder = true; + extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel); + extensions->shaderTextureLOD = true; + extensions->fragDepth = true; + extensions->textureUsage = true; // This could be false since it has no effect in D3D11 + extensions->translatedShaderSource = true; +} + +} + +namespace d3d11 +{ + +void 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); + + outSubresourceData->resize(mipLevels); + outData->resize(mipLevels); + + for (unsigned int i = 0; i < mipLevels; i++) + { + unsigned int mipWidth = std::max(width >> i, 1U); + unsigned int mipHeight = std::max(height >> i, 1U); + unsigned int mipDepth = std::max(depth >> i, 1U); + + unsigned int rowWidth = d3d11::GetFormatPixelBytes(dxgiFormat) * mipWidth; + unsigned int imageSize = rowWidth * height; + + outData->at(i).resize(rowWidth * mipHeight * mipDepth); + initializeFunc(mipWidth, mipHeight, mipDepth, outData->at(i).data(), rowWidth, imageSize); + + outSubresourceData->at(i).pSysMem = outData->at(i).data(); + outSubresourceData->at(i).SysMemPitch = rowWidth; + outSubresourceData->at(i).SysMemSlicePitch = imageSize; + } +} + +void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v) +{ + vertex->x = x; + vertex->y = y; + vertex->u = u; + vertex->v = v; +} + +void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y, + unsigned int layer, float u, float v, float s) +{ + vertex->x = x; + vertex->y = y; + vertex->l = layer; + vertex->u = u; + vertex->v = v; + vertex->s = s; +} + +HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) +{ +#if defined(_DEBUG) + return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name); +#else + return S_OK; +#endif +} + +} + +} 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 new file mode 100644 index 0000000000..4de9bfa86d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h @@ -0,0 +1,173 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// renderer11_utils.h: Conversion functions and other utility routines +// specific to the D3D11 renderer. + +#ifndef LIBGLESV2_RENDERER_RENDERER11_UTILS_H +#define LIBGLESV2_RENDERER_RENDERER11_UTILS_H + +#include "libGLESv2/angletypes.h" +#include "libGLESv2/Caps.h" + +namespace rx +{ + +namespace gl_d3d11 +{ + +D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha); +D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp); +UINT8 ConvertColorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha); + +D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode); + +D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison); +D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled); +UINT8 ConvertStencilMask(GLuint stencilmask); +D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp); + +D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy, GLenum comparisonMode); +D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap); + +D3D11_QUERY ConvertQueryType(GLenum queryType); + +} + +namespace d3d11_gl +{ + +void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions); + +} + +namespace d3d11 +{ + +void GenerateInitialTextureData(GLint internalFormat, GLuint width, GLuint height, GLuint depth, + GLuint mipLevels, std::vector *outSubresourceData, + std::vector< std::vector > *outData); + +struct PositionTexCoordVertex +{ + float x, y; + float u, v; +}; +void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v); + +struct PositionLayerTexCoord3DVertex +{ + float x, y; + unsigned int l; + float u, v, s; +}; +void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, float x, float y, + unsigned int layer, float u, float v, float s); + +template +struct PositionDepthColorVertex +{ + float x, y, z; + T r, g, b, a; +}; + +template +void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z, + const gl::Color &color) +{ + vertex->x = x; + vertex->y = y; + vertex->z = z; + vertex->r = color.red; + vertex->g = color.green; + vertex->b = color.blue; + vertex->a = color.alpha; +} + +HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name); + +template +outType* DynamicCastComObject(IUnknown* object) +{ + outType *outObject = NULL; + HRESULT result = object->QueryInterface(__uuidof(outType), reinterpret_cast(&outObject)); + if (SUCCEEDED(result)) + { + return outObject; + } + else + { + SafeRelease(outObject); + return NULL; + } +} + +inline bool isDeviceLostError(HRESULT errorCode) +{ + switch (errorCode) + { + case DXGI_ERROR_DEVICE_HUNG: + case DXGI_ERROR_DEVICE_REMOVED: + case DXGI_ERROR_DEVICE_RESET: + case DXGI_ERROR_DRIVER_INTERNAL_ERROR: + case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE: + return true; + default: + return false; + } +} + +template +inline ID3D11VertexShader *CompileVS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +{ + ID3D11VertexShader *vs = NULL; + HRESULT result = device->CreateVertexShader(byteCode, N, NULL, &vs); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + SetDebugName(vs, name); + return vs; +} + +template +inline ID3D11GeometryShader *CompileGS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +{ + ID3D11GeometryShader *gs = NULL; + HRESULT result = device->CreateGeometryShader(byteCode, N, NULL, &gs); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + SetDebugName(gs, name); + return gs; +} + +template +inline ID3D11PixelShader *CompilePS(ID3D11Device *device, const BYTE (&byteCode)[N], const char *name) +{ + ID3D11PixelShader *ps = NULL; + HRESULT result = device->CreatePixelShader(byteCode, N, NULL, &ps); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + SetDebugName(ps, name); + return ps; +} + +// Copy data to small D3D11 buffers, such as for small constant buffers, which use one struct to +// represent an entire buffer. +template +inline void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBuffer, const T &value) +{ + D3D11_MAPPED_SUBRESOURCE mappedResource; + context->Map(constantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); + + memcpy(mappedResource.pData, &value, sizeof(T)); + + context->Unmap(constantBuffer, 0); +} + +} + +} + +#endif // LIBGLESV2_RENDERER_RENDERER11_UTILS_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl new file mode 100644 index 0000000000..20e6623a30 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl @@ -0,0 +1,76 @@ +Buffer Buffer4F : register(t0); +Buffer Buffer4I : register(t0); +Buffer Buffer4UI : register(t0); + +struct VS_OUTPUT +{ + float4 position : SV_Position; + uint index : TEXCOORD0; + uint slice : LAYER; +}; + +struct GS_OUTPUT +{ + float4 position : SV_Position; + uint index : TEXCOORD0; + uint slice : SV_RenderTargetArrayIndex; +}; + +cbuffer BufferCopyParams : register(b0) +{ + uint FirstPixelOffset; + uint PixelsPerRow; + uint RowStride; + uint RowsPerSlice; + float2 PositionOffset; + float2 PositionScale; + int2 TexLocationOffset; + int2 TexLocationScale; +} + +void ComputePositionAndIndex(uint vertexID, out VS_OUTPUT outVertex) +{ + uint PixelsPerSlice = PixelsPerRow * RowsPerSlice; + uint SliceStride = RowStride * RowsPerSlice; + + uint slice = vertexID / PixelsPerSlice; + uint sliceOffset = slice * PixelsPerSlice; + uint row = (vertexID - sliceOffset) / PixelsPerRow; + uint col = vertexID - sliceOffset - (row * PixelsPerRow); + + float2 coords = float2(float(col), float(row)); + + outVertex.position = float4(PositionOffset + PositionScale * coords, 0.0f, 1.0f); + outVertex.index = FirstPixelOffset + slice * SliceStride + row * RowStride + col; + outVertex.slice = slice; +} + +void VS_BufferToTexture(in uint vertexID : SV_VertexID, out VS_OUTPUT outVertex) +{ + ComputePositionAndIndex(vertexID, outVertex); +} + +[maxvertexcount(1)] +void GS_BufferToTexture(point VS_OUTPUT inVertex[1], inout PointStream outStream) +{ + GS_OUTPUT outVertex; + outVertex.position = inVertex[0].position; + outVertex.index = inVertex[0].index; + outVertex.slice = inVertex[0].slice; + outStream.Append(outVertex); +} + +float4 PS_BufferToTexture_4F(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target +{ + return Buffer4F.Load(inIndex); +} + +int4 PS_BufferToTexture_4I(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target +{ + return Buffer4I.Load(inIndex); +} + +uint4 PS_BufferToTexture_4UI(in float4 inPosition : SV_Position, in uint inIndex : TEXCOORD0) : SV_Target +{ + return Buffer4UI.Load(inIndex); +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl new file mode 100644 index 0000000000..b4cf38076e --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl @@ -0,0 +1,106 @@ +// Assume we are in SM4+, which has 8 color outputs + +void VS_ClearFloat( in float3 inPosition : POSITION, in float4 inColor : COLOR, + out float4 outPosition : SV_POSITION, out float4 outColor : COLOR) +{ + outPosition = float4(inPosition, 1.0f); + outColor = inColor; +} + +struct PS_OutputFloat +{ + float4 color0 : SV_TARGET0; + float4 color1 : SV_TARGET1; + float4 color2 : SV_TARGET2; + float4 color3 : SV_TARGET3; +#if SM4 + float4 color4 : SV_TARGET4; + float4 color5 : SV_TARGET5; + float4 color6 : SV_TARGET6; + float4 color7 : SV_TARGET7; +#endif +}; + +PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) +{ + PS_OutputFloat outColor; + outColor.color0 = inColor; + outColor.color1 = inColor; + outColor.color2 = inColor; + outColor.color3 = inColor; +#if SM4 + outColor.color4 = inColor; + outColor.color5 = inColor; + outColor.color6 = inColor; + outColor.color7 = inColor; +#endif + return outColor; +} + + +void VS_ClearUint( in float3 inPosition : POSITION, in uint4 inColor : COLOR, + out float4 outPosition : SV_POSITION, out uint4 outColor : COLOR) +{ + outPosition = float4(inPosition, 1.0f); + outColor = inColor; +} + +struct PS_OutputUint +{ + uint4 color0 : SV_TARGET0; + uint4 color1 : SV_TARGET1; + uint4 color2 : SV_TARGET2; + uint4 color3 : SV_TARGET3; + uint4 color4 : SV_TARGET4; + uint4 color5 : SV_TARGET5; + uint4 color6 : SV_TARGET6; + uint4 color7 : SV_TARGET7; +}; + +PS_OutputUint PS_ClearUint(in float4 inPosition : SV_POSITION, in uint4 inColor : COLOR) +{ + PS_OutputUint outColor; + outColor.color0 = inColor; + outColor.color1 = inColor; + outColor.color2 = inColor; + outColor.color3 = inColor; + outColor.color4 = inColor; + outColor.color5 = inColor; + outColor.color6 = inColor; + outColor.color7 = inColor; + return outColor; +} + + +void VS_ClearSint( in float3 inPosition : POSITION, in int4 inColor : COLOR, + out float4 outPosition : SV_POSITION, out int4 outColor : COLOR) +{ + outPosition = float4(inPosition, 1.0f); + outColor = inColor; +} + +struct PS_OutputSint +{ + int4 color0 : SV_TARGET0; + int4 color1 : SV_TARGET1; + int4 color2 : SV_TARGET2; + int4 color3 : SV_TARGET3; + int4 color4 : SV_TARGET4; + int4 color5 : SV_TARGET5; + int4 color6 : SV_TARGET6; + int4 color7 : SV_TARGET7; +}; + +PS_OutputSint PS_ClearSint(in float4 inPosition : SV_POSITION, in int4 inColor : COLOR) +{ + PS_OutputSint outColor; + outColor.color0 = inColor; + outColor.color1 = inColor; + outColor.color2 = inColor; + outColor.color3 = inColor; + outColor.color4 = inColor; + outColor.color5 = inColor; + outColor.color6 = inColor; + outColor.color7 = inColor; + return outColor; +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl new file mode 100644 index 0000000000..8671c39fb7 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl @@ -0,0 +1,111 @@ +Texture2D TextureF : register(t0); +Texture2D TextureUI : register(t0); +Texture2D TextureI : register(t0); + +SamplerState Sampler : register(s0); + +void VS_Passthrough2D( in float2 inPosition : POSITION, in float2 inTexCoord : TEXCOORD0, + out float4 outPosition : SV_POSITION, out float2 outTexCoord : TEXCOORD0) +{ + outPosition = float4(inPosition, 0.0f, 1.0f); + outTexCoord = inTexCoord; +} + +float PS_PassthroughDepth2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_DEPTH +{ + return TextureF.Sample(Sampler, inTexCoord).r; +} + +float4 PS_PassthroughRGBA2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return TextureF.Sample(Sampler, inTexCoord).rgba; +} + +uint4 PS_PassthroughRGBA2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI.GetDimensions(size.x, size.y); + + return TextureUI.Load(int3(size * inTexCoord, 0)).rgba; +} + +int4 PS_PassthroughRGBA2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI.GetDimensions(size.x, size.y); + + return TextureI.Load(int3(size * inTexCoord, 0)).rgba; +} + +float4 PS_PassthroughRGB2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, inTexCoord).rgb, 1.0f); +} + +uint4 PS_PassthroughRGB2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI.GetDimensions(size.x, size.y); + + return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).rgb, 0); +} + +int4 PS_PassthroughRGB2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI.GetDimensions(size.x, size.y); + + return int4(TextureI.Load(int3(size * inTexCoord, 0)).rgb, 0); +} + +float4 PS_PassthroughRG2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, inTexCoord).rg, 0.0f, 1.0f); +} + +uint4 PS_PassthroughRG2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI.GetDimensions(size.x, size.y); + + return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).rg, 0, 0); +} + +int4 PS_PassthroughRG2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI.GetDimensions(size.x, size.y); + + return int4(TextureI.Load(int3(size * inTexCoord, 0)).rg, 0, 0); +} + +float4 PS_PassthroughR2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, inTexCoord).r, 0.0f, 0.0f, 1.0f); +} + +uint4 PS_PassthroughR2DUI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI.GetDimensions(size.x, size.y); + + return uint4(TextureUI.Load(int3(size * inTexCoord, 0)).r, 0, 0, 0); +} + +int4 PS_PassthroughR2DI(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI.GetDimensions(size.x, size.y); + + return int4(TextureI.Load(int3(size * inTexCoord, 0)).r, 0, 0, 0); +} + +float4 PS_PassthroughLum2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, inTexCoord).rrr, 1.0f); +} + +float4 PS_PassthroughLumAlpha2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return TextureF.Sample(Sampler, inTexCoord).rrra; +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl new file mode 100644 index 0000000000..c23c9032ec --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl @@ -0,0 +1,146 @@ +Texture3D TextureF : register(t0); +Texture3D TextureUI : register(t0); +Texture3D TextureI : register(t0); + +SamplerState Sampler : register(s0); + +struct VS_INPUT +{ + float2 Position : POSITION; + uint Layer : LAYER; + float3 TexCoord : TEXCOORD; +}; + +struct VS_OUTPUT +{ + float4 Position : SV_POSITION; + uint Layer : LAYER; + float3 TexCoord : TEXCOORD; +}; + +struct GS_OUTPUT +{ + float4 Position : SV_POSITION; + uint Layer : SV_RENDERTARGETARRAYINDEX; + float3 TexCoord : TEXCOORD; +}; + +VS_OUTPUT VS_Passthrough3D(VS_INPUT input) +{ + VS_OUTPUT output; + + output.Position = float4(input.Position, 0.0f, 1.0f); + output.Layer = input.Layer; + output.TexCoord = input.TexCoord; + + return output; +} + +[maxvertexcount(3)] +void GS_Passthrough3D(triangle VS_OUTPUT input[3], inout TriangleStream outputStream) +{ + GS_OUTPUT output; + + for (int i = 0; i < 3; i++) + { + output.Position = input[i].Position; + output.Layer = input[i].Layer; + output.TexCoord = input[i].TexCoord; + + outputStream.Append(output); + } +} + +float4 PS_PassthroughRGBA3D(GS_OUTPUT input) : SV_TARGET0 +{ + return TextureF.Sample(Sampler, input.TexCoord).rgba; +} + +uint4 PS_PassthroughRGBA3DUI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureUI.GetDimensions(size.x, size.y, size.z); + + return TextureUI.Load(int4(size * input.TexCoord, 0)).rgba; +} + +int4 PS_PassthroughRGBA3DI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureI.GetDimensions(size.x, size.y, size.z); + + return TextureI.Load(int4(size * input.TexCoord, 0)).rgba; +} + +float4 PS_PassthroughRGB3D(GS_OUTPUT input) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, input.TexCoord).rgb, 1.0f); +} + +uint4 PS_PassthroughRGB3DUI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureUI.GetDimensions(size.x, size.y, size.z); + + return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).rgb, 0); +} + +int4 PS_PassthroughRGB3DI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureI.GetDimensions(size.x, size.y, size.z); + + return int4(TextureI.Load(int4(size * input.TexCoord, 0)).rgb, 0); +} + +float4 PS_PassthroughRG3D(GS_OUTPUT input) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, input.TexCoord).rg, 0.0f, 1.0f); +} + +uint4 PS_PassthroughRG3DUI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureUI.GetDimensions(size.x, size.y, size.z); + + return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).rg, 0, 0); +} + +int4 PS_PassthroughRG3DI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureI.GetDimensions(size.x, size.y, size.z); + + return int4(TextureI.Load(int4(size * input.TexCoord, 0)).rg, 0, 0); +} + +float4 PS_PassthroughR3D(GS_OUTPUT input) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, input.TexCoord).r, 0.0f, 0.0f, 1.0f); +} + +uint4 PS_PassthroughR3DUI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureUI.GetDimensions(size.x, size.y, size.z); + + return uint4(TextureUI.Load(int4(size * input.TexCoord, 0)).r, 0, 0, 0); +} + +int4 PS_PassthroughR3DI(GS_OUTPUT input) : SV_TARGET0 +{ + uint3 size; + TextureI.GetDimensions(size.x, size.y, size.z); + + return int4(TextureI.Load(int4(size * input.TexCoord, 0)).r, 0, 0, 0); +} + +float4 PS_PassthroughLum3D(GS_OUTPUT input) : SV_TARGET0 +{ + return float4(TextureF.Sample(Sampler, input.TexCoord).rrr, 1.0f); +} + +float4 PS_PassthroughLumAlpha3D(GS_OUTPUT input) : SV_TARGET0 +{ + return TextureF.Sample(Sampler, input.TexCoord).rrra; +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl new file mode 100644 index 0000000000..505e222137 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl @@ -0,0 +1,99 @@ +Texture2D TextureF2D : register(t0); +Texture2D TextureUI2D : register(t0); +Texture2D TextureI2D : register(t0); + +Texture3D TextureF3D : register(t0); +Texture3D TextureUI3D : register(t0); +Texture3D TextureI3D : register(t0); + +Texture2DArray TextureF2DArray : register(t0); +Texture2DArray TextureUI2DArray : register(t0); +Texture2DArray TextureI2DArray : register(t0); + +SamplerState Sampler : register(s0); + +cbuffer SwizzleProperties : register(b0) +{ + uint4 SwizzleIndices : packoffset(c0); +} + +float4 SwizzleLookup(in float4 sample) +{ + float lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f }; + return float4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]); +} + +int4 SwizzleLookup(in int4 sample) +{ + int lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f }; + return int4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]); +} + +uint4 SwizzleLookup(in uint4 sample) +{ + uint lookup[6] = { sample[0], sample[1], sample[2], sample[3], 0.0f, 1.0f }; + return uint4(lookup[SwizzleIndices[0]], lookup[SwizzleIndices[1]], lookup[SwizzleIndices[2]], lookup[SwizzleIndices[3]]); +} + +float4 PS_SwizzleF2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return SwizzleLookup(TextureF2D.Sample(Sampler, inTexCoord)); +} + +int4 PS_SwizzleI2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureI2D.GetDimensions(size.x, size.y); + + return SwizzleLookup(TextureI2D.Load(int3(size * inTexCoord, 0))); +} + +uint4 PS_SwizzleUI2D(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint2 size; + TextureUI2D.GetDimensions(size.x, size.y); + + return SwizzleLookup(TextureUI2D.Load(int3(size * inTexCoord, 0))); +} + +float4 PS_SwizzleF3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return SwizzleLookup(TextureF3D.Sample(Sampler, inTexCoord)); +} + +int4 PS_SwizzleI3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint3 size; + TextureI3D.GetDimensions(size.x, size.y, size.z); + + return SwizzleLookup(TextureI3D.Load(int4(size * inTexCoord, 0))); +} + +uint4 PS_SwizzleUI3D(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint3 size; + TextureUI3D.GetDimensions(size.x, size.y, size.z); + + return SwizzleLookup(TextureUI3D.Load(int4(size * inTexCoord, 0))); +} + +float4 PS_SwizzleF2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + return SwizzleLookup(TextureF2DArray.Sample(Sampler, float3(inTexCoord.xy, inLayer))); +} + +int4 PS_SwizzleI2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint3 size; + TextureI2DArray.GetDimensions(size.x, size.y, size.z); + + return SwizzleLookup(TextureI2DArray.Load(int4(size.xy * inTexCoord.xy, inLayer, 0))); +} + +uint4 PS_SwizzleUI2DArray(in float4 inPosition : SV_POSITION, in uint inLayer : SV_RENDERTARGETARRAYINDEX, in float3 inTexCoord : TEXCOORD0) : SV_TARGET0 +{ + uint3 size; + TextureUI2DArray.GetDimensions(size.x, size.y, size.z); + + return SwizzleLookup(TextureUI2DArray.Load(int4(size.xy * inTexCoord.xy, inLayer, 0))); +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp new file mode 100644 index 0000000000..f486e5a4cc --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp @@ -0,0 +1,645 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// 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" +#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" + +namespace +{ +#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/standardvs.h" +#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/flipyvs.h" +#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/passthroughps.h" +#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/luminanceps.h" +#include "libGLESv2/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h" + +const BYTE* const g_shaderCode[] = +{ + g_vs20_VS_standard, + g_vs20_VS_flipy, + g_ps20_PS_passthrough, + g_ps20_PS_luminance, + g_ps20_PS_componentmask +}; + +const size_t g_shaderSize[] = +{ + sizeof(g_vs20_VS_standard), + sizeof(g_vs20_VS_flipy), + sizeof(g_ps20_PS_passthrough), + sizeof(g_ps20_PS_luminance), + sizeof(g_ps20_PS_componentmask) +}; +} + +namespace rx +{ +Blit9::Blit9(rx::Renderer9 *renderer) + : mRenderer(renderer), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedStateBlock(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL) +{ + initGeometry(); + memset(mCompiledShaders, 0, sizeof(mCompiledShaders)); +} + +Blit9::~Blit9() +{ + SafeRelease(mSavedStateBlock); + SafeRelease(mQuadVertexBuffer); + SafeRelease(mQuadVertexDeclaration); + + for (int i = 0; i < SHADER_COUNT; i++) + { + SafeRelease(mCompiledShaders[i]); + } +} + +void Blit9::initGeometry() +{ + static const float quad[] = + { + -1, -1, + -1, 1, + 1, -1, + 1, 1 + }; + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::error(GL_OUT_OF_MEMORY); + } + + void *lockPtr = NULL; + result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0); + + if (FAILED(result) || lockPtr == NULL) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::error(GL_OUT_OF_MEMORY); + } + + memcpy(lockPtr, quad, sizeof(quad)); + mQuadVertexBuffer->Unlock(); + + static const D3DVERTEXELEMENT9 elements[] = + { + { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, + D3DDECL_END() + }; + + result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::error(GL_OUT_OF_MEMORY); + } +} + +template +bool Blit9::setShader(ShaderId source, const char *profile, + D3DShaderType *(rx::Renderer9::*createShader)(const DWORD *, size_t length), + HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)) +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + D3DShaderType *shader; + + if (mCompiledShaders[source] != NULL) + { + shader = static_cast(mCompiledShaders[source]); + } + else + { + const BYTE* shaderCode = g_shaderCode[source]; + size_t shaderSize = g_shaderSize[source]; + + shader = (mRenderer->*createShader)(reinterpret_cast(shaderCode), shaderSize); + if (!shader) + { + ERR("Failed to create shader for blit operation"); + return false; + } + + mCompiledShaders[source] = shader; + } + + HRESULT hr = (device->*setShader)(shader); + + if (FAILED(hr)) + { + ERR("Failed to set shader for blit operation"); + return false; + } + + return true; +} + +bool Blit9::setVertexShader(ShaderId shader) +{ + return setShader(shader, "vs_2_0", &rx::Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader); +} + +bool Blit9::setPixelShader(ShaderId shader) +{ + return setShader(shader, "ps_2_0", &rx::Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader); +} + +RECT Blit9::getSurfaceRect(IDirect3DSurface9 *surface) const +{ + D3DSURFACE_DESC desc; + surface->GetDesc(&desc); + + RECT rect; + rect.left = 0; + rect.top = 0; + rect.right = desc.Width; + rect.bottom = desc.Height; + + return rect; +} + +bool Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) +{ + IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source)); + if (!texture) + { + return false; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + saveState(); + + device->SetTexture(0, texture); + device->SetRenderTarget(0, dest); + + setVertexShader(SHADER_VS_STANDARD); + setPixelShader(SHADER_PS_PASSTHROUGH); + + setCommonBlitState(); + device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + + setViewport(getSurfaceRect(dest), 0, 0); + + render(); + + SafeRelease(texture); + + restoreState(); + + return true; +} + +bool Blit9::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) +{ + RenderTarget9 *renderTarget = NULL; + IDirect3DSurface9 *source = NULL; + gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); + + if (colorbuffer) + { + renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); + } + + if (renderTarget) + { + source = renderTarget->getSurface(); + } + + if (!source) + { + ERR("Failed to retrieve the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); + IDirect3DSurface9 *destSurface = storage9->getSurfaceLevel(level, true); + bool result = false; + + if (destSurface) + { + result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); + SafeRelease(destSurface); + } + + SafeRelease(source); + return result; +} + +bool Blit9::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) +{ + RenderTarget9 *renderTarget = NULL; + IDirect3DSurface9 *source = NULL; + gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); + + if (colorbuffer) + { + renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); + } + + if (renderTarget) + { + source = renderTarget->getSurface(); + } + + if (!source) + { + ERR("Failed to retrieve the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); + IDirect3DSurface9 *destSurface = storage9->getCubeMapSurface(target, level, true); + bool result = false; + + if (destSurface) + { + result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); + SafeRelease(destSurface); + } + + SafeRelease(source); + return result; +} + +bool Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) +{ + if (!dest) + { + return false; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + D3DSURFACE_DESC sourceDesc; + D3DSURFACE_DESC destDesc; + source->GetDesc(&sourceDesc); + dest->GetDesc(&destDesc); + + if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET && + d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect + { + RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)}; + HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::error(GL_OUT_OF_MEMORY, false); + } + } + else + { + return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest); + } + return true; +} + +bool Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) +{ + IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect); + if (!texture) + { + return false; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + saveState(); + + device->SetTexture(0, texture); + device->SetRenderTarget(0, dest); + + setViewport(sourceRect, xoffset, yoffset); + + setCommonBlitState(); + if (setFormatConvertShaders(destFormat)) + { + render(); + } + + SafeRelease(texture); + + restoreState(); + + return true; +} + +bool Blit9::setFormatConvertShaders(GLenum destFormat) +{ + bool okay = setVertexShader(SHADER_VS_STANDARD); + + switch (destFormat) + { + default: UNREACHABLE(); + case GL_RGBA: + case GL_BGRA_EXT: + case GL_RGB: + case GL_RG_EXT: + case GL_RED_EXT: + case GL_ALPHA: + okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK); + break; + + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + okay = okay && setPixelShader(SHADER_PS_LUMINANCE); + break; + } + + if (!okay) + { + return false; + } + + enum { X = 0, Y = 1, Z = 2, W = 3 }; + + // The meaning of this constant depends on the shader that was selected. + // See the shader assembly code above for details. + // Allocate one array for both registers and split it into two float4's. + float psConst[8] = { 0 }; + float *multConst = &psConst[0]; + float *addConst = &psConst[4]; + + switch (destFormat) + { + default: UNREACHABLE(); + case GL_RGBA: + case GL_BGRA_EXT: + multConst[X] = 1; + multConst[Y] = 1; + multConst[Z] = 1; + multConst[W] = 1; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 0; + break; + + case GL_RGB: + multConst[X] = 1; + multConst[Y] = 1; + multConst[Z] = 1; + multConst[W] = 0; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 1; + break; + + case GL_RG_EXT: + multConst[X] = 1; + multConst[Y] = 1; + multConst[Z] = 0; + multConst[W] = 0; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 1; + break; + + case GL_RED_EXT: + multConst[X] = 1; + multConst[Y] = 0; + multConst[Z] = 0; + multConst[W] = 0; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 1; + break; + + case GL_ALPHA: + multConst[X] = 0; + multConst[Y] = 0; + multConst[Z] = 0; + multConst[W] = 1; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 0; + break; + + case GL_LUMINANCE: + multConst[X] = 1; + multConst[Y] = 0; + multConst[Z] = 0; + multConst[W] = 0; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 1; + break; + + case GL_LUMINANCE_ALPHA: + multConst[X] = 1; + multConst[Y] = 0; + multConst[Z] = 0; + multConst[W] = 1; + addConst[X] = 0; + addConst[Y] = 0; + addConst[Z] = 0; + addConst[W] = 0; + break; + } + + mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst, 2); + + return true; +} + +IDirect3DTexture9 *Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect) +{ + if (!surface) + { + return NULL; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + D3DSURFACE_DESC sourceDesc; + surface->GetDesc(&sourceDesc); + + // Copy the render target into a texture + IDirect3DTexture9 *texture; + HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); + } + + IDirect3DSurface9 *textureSurface; + result = texture->GetSurfaceLevel(0, &textureSurface); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + SafeRelease(texture); + return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); + } + + mRenderer->endScene(); + result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE); + + SafeRelease(textureSurface); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + SafeRelease(texture); + return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); + } + + return texture; +} + +void Blit9::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset) +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + D3DVIEWPORT9 vp; + vp.X = xoffset; + vp.Y = yoffset; + vp.Width = sourceRect.right - sourceRect.left; + vp.Height = sourceRect.bottom - sourceRect.top; + vp.MinZ = 0.0f; + vp.MaxZ = 1.0f; + device->SetViewport(&vp); + + float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 }; + device->SetVertexShaderConstantF(0, halfPixelAdjust, 1); +} + +void Blit9::setCommonBlitState() +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + device->SetDepthStencilSurface(NULL); + + device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); + device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); + device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); + + device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE); + device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + + RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle + device->SetScissorRect(&scissorRect); + + for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + device->SetStreamSourceFreq(i, 1); + } +} + +void Blit9::render() +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float)); + hr = device->SetVertexDeclaration(mQuadVertexDeclaration); + + mRenderer->startScene(); + hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); +} + +void Blit9::saveState() +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + HRESULT hr; + + device->GetDepthStencilSurface(&mSavedDepthStencil); + device->GetRenderTarget(0, &mSavedRenderTarget); + + if (mSavedStateBlock == NULL) + { + hr = device->BeginStateBlock(); + ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); + + setCommonBlitState(); + + static const float dummyConst[8] = { 0 }; + + device->SetVertexShader(NULL); + device->SetVertexShaderConstantF(0, dummyConst, 2); + device->SetPixelShader(NULL); + device->SetPixelShaderConstantF(0, dummyConst, 2); + + D3DVIEWPORT9 dummyVp; + dummyVp.X = 0; + dummyVp.Y = 0; + dummyVp.Width = 1; + dummyVp.Height = 1; + dummyVp.MinZ = 0; + dummyVp.MaxZ = 1; + + device->SetViewport(&dummyVp); + + device->SetTexture(0, NULL); + + device->SetStreamSource(0, mQuadVertexBuffer, 0, 0); + + device->SetVertexDeclaration(mQuadVertexDeclaration); + + hr = device->EndStateBlock(&mSavedStateBlock); + ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); + } + + ASSERT(mSavedStateBlock != NULL); + + if (mSavedStateBlock != NULL) + { + hr = mSavedStateBlock->Capture(); + ASSERT(SUCCEEDED(hr)); + } +} + +void Blit9::restoreState() +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + device->SetDepthStencilSurface(mSavedDepthStencil); + SafeRelease(mSavedDepthStencil); + + device->SetRenderTarget(0, mSavedRenderTarget); + SafeRelease(mSavedRenderTarget); + + ASSERT(mSavedStateBlock != NULL); + + if (mSavedStateBlock != NULL) + { + mSavedStateBlock->Apply(); + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h new file mode 100644 index 0000000000..3635bca932 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h @@ -0,0 +1,94 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Blit9.cpp: Surface copy utility class. + +#ifndef LIBGLESV2_BLIT9_H_ +#define LIBGLESV2_BLIT9_H_ + +#include "common/angleutils.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer9; +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; + +class Blit9 +{ + public: + explicit Blit9(Renderer9 *renderer); + ~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); + + // Copy from source surface to dest surface. + // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) + // source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0. + bool formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); + + // 2x2 box filter sample from source to dest. + // Requires that source is RGB(A) and dest has the same format as source. + bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); + + private: + rx::Renderer9 *mRenderer; + + IDirect3DVertexBuffer9 *mQuadVertexBuffer; + IDirect3DVertexDeclaration9 *mQuadVertexDeclaration; + + void initGeometry(); + + bool setFormatConvertShaders(GLenum destFormat); + + bool copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); + IDirect3DTexture9 *copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect); + void setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset); + void setCommonBlitState(); + RECT getSurfaceRect(IDirect3DSurface9 *surface) const; + + // This enum is used to index mCompiledShaders and mShaderSource. + enum ShaderId + { + SHADER_VS_STANDARD, + SHADER_VS_FLIPY, + SHADER_PS_PASSTHROUGH, + SHADER_PS_LUMINANCE, + SHADER_PS_COMPONENTMASK, + SHADER_COUNT + }; + + // This actually contains IDirect3DVertexShader9 or IDirect3DPixelShader9 casted to IUnknown. + IUnknown *mCompiledShaders[SHADER_COUNT]; + + template + bool setShader(ShaderId source, const char *profile, + D3DShaderType *(Renderer9::*createShader)(const DWORD *, size_t length), + HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)); + + bool setVertexShader(ShaderId shader); + bool setPixelShader(ShaderId shader); + void render(); + + void saveState(); + void restoreState(); + IDirect3DStateBlock9 *mSavedStateBlock; + IDirect3DSurface9 *mSavedRenderTarget; + IDirect3DSurface9 *mSavedDepthStencil; + + DISALLOW_COPY_AND_ASSIGN(Blit9); +}; +} + +#endif // LIBGLESV2_BLIT9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp new file mode 100644 index 0000000000..347bde0c65 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp @@ -0,0 +1,126 @@ +#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. +// + +// Buffer9.cpp Defines the Buffer9 class. + +#include "libGLESv2/renderer/d3d/d3d9/Buffer9.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ + +Buffer9::Buffer9(rx::Renderer9 *renderer) + : BufferD3D(), + mRenderer(renderer), + mSize(0) +{ + +} + +Buffer9::~Buffer9() +{ + +} + +Buffer9 *Buffer9::makeBuffer9(BufferImpl *buffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(Buffer9*, buffer)); + return static_cast(buffer); +} + +void Buffer9::clear() +{ + mSize = 0; +} + +void 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); + } + } + + mSize = size; + if (data) + { + memcpy(mMemory.data(), data, size); + } + + mIndexRangeCache.clear(); + + invalidateStaticData(); + + if (usage == GL_STATIC_DRAW) + { + initializeStaticData(); + } +} + +void *Buffer9::getData() +{ + return mMemory.data(); +} + +void 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); + } + } + + mSize = std::max(mSize, offset + size); + if (data) + { + memcpy(mMemory.data() + offset, data, size); + } + + mIndexRangeCache.invalidateRange(offset, size); + + invalidateStaticData(); +} + +void Buffer9::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) +{ + Buffer9* sourceBuffer = makeBuffer9(source); + if (sourceBuffer) + { + memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size); + } + + invalidateStaticData(); +} + +// We do not suppot buffer mapping in D3D9 +GLvoid* Buffer9::map(size_t offset, size_t length, GLbitfield access) +{ + UNREACHABLE(); + return NULL; +} + +void Buffer9::unmap() +{ + UNREACHABLE(); +} + +void Buffer9::markTransformFeedbackUsage() +{ + UNREACHABLE(); +} + +Renderer* Buffer9::getRenderer() +{ + return mRenderer; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h new file mode 100644 index 0000000000..ec25ec30c9 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h @@ -0,0 +1,53 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Buffer9.h: Defines the rx::Buffer9 class which implements rx::BufferImpl via rx::BufferD3D. + +#ifndef LIBGLESV2_RENDERER_BUFFER9_H_ +#define LIBGLESV2_RENDERER_BUFFER9_H_ + +#include "libGLESv2/renderer/d3d/BufferD3D.h" +#include "libGLESv2/renderer/d3d/MemoryBuffer.h" +#include "libGLESv2/angletypes.h" + +namespace rx +{ +class Renderer9; + +class Buffer9 : public BufferD3D +{ + public: + Buffer9(rx::Renderer9 *renderer); + virtual ~Buffer9(); + + static Buffer9 *makeBuffer9(BufferImpl *buffer); + + // 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 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 void markTransformFeedbackUsage(); + + private: + DISALLOW_COPY_AND_ASSIGN(Buffer9); + + rx::Renderer9 *mRenderer; + MemoryBuffer mMemory; + size_t mSize; +}; + +} + +#endif // LIBGLESV2_RENDERER_BUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp new file mode 100644 index 0000000000..d2437cadf3 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp @@ -0,0 +1,73 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Fence9.cpp: Defines the rx::Fence9 class. + +#include "libGLESv2/renderer/d3d/d3d9/Fence9.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ + +Fence9::Fence9(rx::Renderer9 *renderer) +{ + mRenderer = renderer; + mQuery = NULL; +} + +Fence9::~Fence9() +{ + SafeRelease(mQuery); +} + +bool Fence9::isSet() const +{ + return mQuery != NULL; +} + +void Fence9::set() +{ + if (!mQuery) + { + mQuery = mRenderer->allocateEventQuery(); + if (!mQuery) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + HRESULT result = mQuery->Issue(D3DISSUE_END); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); +} + +bool Fence9::test(bool flushCommandBuffer) +{ + ASSERT(mQuery); + + DWORD getDataFlags = (flushCommandBuffer ? D3DGETDATA_FLUSH : 0); + HRESULT result = mQuery->GetData(NULL, 0, getDataFlags); + + if (d3d9::isDeviceLostError(result)) + { + mRenderer->notifyDeviceLost(); + return gl::error(GL_OUT_OF_MEMORY, true); + } + + ASSERT(result == S_OK || result == S_FALSE); + + return (result == S_OK); +} + +bool Fence9::hasError() const +{ + return mRenderer->isDeviceLost(); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h new file mode 100644 index 0000000000..e923a2178c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h @@ -0,0 +1,38 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Fence9.h: Defines the rx::Fence9 class which implements rx::FenceImpl. + +#ifndef LIBGLESV2_RENDERER_FENCE9_H_ +#define LIBGLESV2_RENDERER_FENCE9_H_ + +#include "libGLESv2/renderer/FenceImpl.h" + +namespace rx +{ +class Renderer9; + +class Fence9 : public FenceImpl +{ + public: + explicit Fence9(rx::Renderer9 *renderer); + virtual ~Fence9(); + + bool isSet() const; + void set(); + bool test(bool flushCommandBuffer); + bool hasError() const; + + private: + DISALLOW_COPY_AND_ASSIGN(Fence9); + + rx::Renderer9 *mRenderer; + IDirect3DQuery9 *mQuery; +}; + +} + +#endif // LIBGLESV2_RENDERER_FENCE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp new file mode 100644 index 0000000000..e237c3b6e1 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp @@ -0,0 +1,703 @@ + +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image9.cpp: Implements the rx::Image9 class, which acts as the interface to +// the actual underlying surfaces of a Texture. + +#include "libGLESv2/renderer/d3d/d3d9/Image9.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 +{ + +Image9::Image9() +{ + mSurface = NULL; + mRenderer = NULL; + + mD3DPool = D3DPOOL_SYSTEMMEM; + mD3DFormat = D3DFMT_UNKNOWN; +} + +Image9::~Image9() +{ + SafeRelease(mSurface); +} + +void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface) +{ + D3DSURFACE_DESC destDesc; + HRESULT result = destSurface->GetDesc(&destDesc); + ASSERT(SUCCEEDED(result)); + + D3DSURFACE_DESC sourceDesc; + result = sourceSurface->GetDesc(&sourceDesc); + ASSERT(SUCCEEDED(result)); + + ASSERT(sourceDesc.Format == destDesc.Format); + ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width); + ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height); + + MipGenerationFunction mipFunction = d3d9::GetMipGenerationFunction(sourceDesc.Format); + ASSERT(mipFunction != NULL); + + D3DLOCKED_RECT sourceLocked = {0}; + result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY); + ASSERT(SUCCEEDED(result)); + + D3DLOCKED_RECT destLocked = {0}; + result = destSurface->LockRect(&destLocked, NULL, 0); + ASSERT(SUCCEEDED(result)); + + const uint8_t *sourceData = reinterpret_cast(sourceLocked.pBits); + uint8_t *destData = reinterpret_cast(destLocked.pBits); + + if (sourceData && destData) + { + mipFunction(sourceDesc.Width, sourceDesc.Height, 1, sourceData, sourceLocked.Pitch, 0, + destData, destLocked.Pitch, 0); + } + + destSurface->UnlockRect(); + sourceSurface->UnlockRect(); +} + +Image9 *Image9::makeImage9(Image *img) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::Image9*, img)); + return static_cast(img); +} + +void Image9::generateMipmap(Image9 *dest, Image9 *source) +{ + IDirect3DSurface9 *sourceSurface = source->getSurface(); + if (sourceSurface == NULL) + return gl::error(GL_OUT_OF_MEMORY); + + IDirect3DSurface9 *destSurface = dest->getSurface(); + generateMip(destSurface, sourceSurface); + + dest->markDirty(); +} + +void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source) +{ + D3DLOCKED_RECT sourceLock = {0}; + D3DLOCKED_RECT destLock = {0}; + + source->LockRect(&sourceLock, NULL, 0); + dest->LockRect(&destLock, NULL, 0); + + if (sourceLock.pBits && destLock.pBits) + { + D3DSURFACE_DESC desc; + source->GetDesc(&desc); + + int blockHeight = d3d9::GetBlockHeight(desc.Format); + int rows = desc.Height / blockHeight; + + int bytes = d3d9::GetBlockSize(desc.Format, desc.Width, blockHeight); + ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch); + + for(int i = 0; i < rows; i++) + { + memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes); + } + + source->UnlockRect(); + dest->UnlockRect(); + } + else UNREACHABLE(); +} + +bool Image9::redefine(rx::Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) +{ + // 3D textures are not supported by the D3D9 backend. + ASSERT(depth <= 1); + + // Only 2D and cube texture are supported by the D3D9 backend. + ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP); + + if (mWidth != width || + mHeight != height || + mDepth != depth || + mInternalFormat != internalformat || + forceRelease) + { + mRenderer = Renderer9::makeRenderer9(renderer); + + mWidth = width; + mHeight = height; + mDepth = depth; + mInternalFormat = internalformat; + + // compute the d3d format that will be used + mD3DFormat = gl_d3d9::GetTextureFormat(internalformat); + mActualFormat = d3d9_gl::GetInternalFormat(mD3DFormat); + mRenderable = gl_d3d9::GetRenderFormat(internalformat) != D3DFMT_UNKNOWN; + + SafeRelease(mSurface); + mDirty = gl_d3d9::RequiresTextureDataInitialization(mInternalFormat); + + return true; + } + + return false; +} + +void Image9::createSurface() +{ + if(mSurface) + { + return; + } + + IDirect3DTexture9 *newTexture = NULL; + IDirect3DSurface9 *newSurface = NULL; + const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM; + const D3DFORMAT d3dFormat = getD3DFormat(); + + if (mWidth != 0 && mHeight != 0) + { + int levelToFetch = 0; + GLsizei requestWidth = mWidth; + GLsizei requestHeight = mHeight; + d3d9::MakeValidSize(true, d3dFormat, &requestWidth, &requestHeight, &levelToFetch); + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0, d3dFormat, + poolToUse, &newTexture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + ERR("Creating image surface failed."); + return gl::error(GL_OUT_OF_MEMORY); + } + + newTexture->GetSurfaceLevel(levelToFetch, &newSurface); + SafeRelease(newTexture); + + if (gl_d3d9::RequiresTextureDataInitialization(mInternalFormat)) + { + InitializeTextureDataFunction initializeFunc = gl_d3d9::GetTextureDataInitializationFunction(mInternalFormat); + + RECT entireRect; + entireRect.left = 0; + entireRect.right = mWidth; + entireRect.top = 0; + entireRect.bottom = mHeight; + + D3DLOCKED_RECT lockedRect; + result = newSurface->LockRect(&lockedRect, &entireRect, 0); + ASSERT(SUCCEEDED(result)); + + initializeFunc(mWidth, mHeight, 1, reinterpret_cast(lockedRect.pBits), lockedRect.Pitch, 0); + + result = newSurface->UnlockRect(); + ASSERT(SUCCEEDED(result)); + } + } + + mSurface = newSurface; + mDirty = false; + mD3DPool = poolToUse; +} + +HRESULT Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect) +{ + createSurface(); + + HRESULT result = D3DERR_INVALIDCALL; + + if (mSurface) + { + result = mSurface->LockRect(lockedRect, rect, 0); + ASSERT(SUCCEEDED(result)); + + mDirty = true; + } + + return result; +} + +void Image9::unlock() +{ + if (mSurface) + { + HRESULT result = mSurface->UnlockRect(); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + } +} + +D3DFORMAT Image9::getD3DFormat() const +{ + // this should only happen if the image hasn't been redefined first + // which would be a bug by the caller + ASSERT(mD3DFormat != D3DFMT_UNKNOWN); + + return mD3DFormat; +} + +bool Image9::isDirty() const +{ + // Make sure to that this image is marked as dirty even if the staging texture hasn't been created yet + // if initialization is required before use. + return (mSurface || gl_d3d9::RequiresTextureDataInitialization(mInternalFormat)) && mDirty; +} + +IDirect3DSurface9 *Image9::getSurface() +{ + createSurface(); + + return mSurface; +} + +void Image9::setManagedSurface(TextureStorageInterface2D *storage, int level) +{ + TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); + setManagedSurface(storage9->getSurfaceLevel(level, false)); +} + +void Image9::setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level) +{ + TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); + setManagedSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false)); +} + +void Image9::setManagedSurface(IDirect3DSurface9 *surface) +{ + D3DSURFACE_DESC desc; + surface->GetDesc(&desc); + ASSERT(desc.Pool == D3DPOOL_MANAGED); + + if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight) + { + if (mSurface) + { + copyLockableSurfaces(surface, mSurface); + SafeRelease(mSurface); + } + + mSurface = surface; + mD3DPool = desc.Pool; + } +} + +bool Image9::copyToStorage(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + ASSERT(getSurface() != NULL); + TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); + return 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) +{ + ASSERT(getSurface() != NULL); + TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); + 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) +{ + // 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) +{ + // 2D array textures are not supported by the D3D9 backend. + UNREACHABLE(); + return false; +} + +bool Image9::copyToSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) +{ + ASSERT(width > 0 && height > 0); + + if (!destSurface) + return false; + + IDirect3DSurface9 *sourceSurface = getSurface(); + + if (sourceSurface && sourceSurface != destSurface) + { + RECT rect; + rect.left = xoffset; + rect.top = yoffset; + rect.right = xoffset + width; + rect.bottom = yoffset + height; + + POINT point = {rect.left, rect.top}; + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + if (mD3DPool == D3DPOOL_MANAGED) + { + D3DSURFACE_DESC desc; + sourceSurface->GetDesc(&desc); + + IDirect3DSurface9 *surf = 0; + HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); + + if (SUCCEEDED(result)) + { + copyLockableSurfaces(surf, sourceSurface); + result = device->UpdateSurface(surf, &rect, destSurface, &point); + ASSERT(SUCCEEDED(result)); + SafeRelease(surf); + } + } + else + { + // 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)); + } + } + + SafeRelease(destSurface); + return true; +} + +// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input +// into the target pixel rectangle. +void Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLint unpackAlignment, GLenum type, const void *input) +{ + // 3D textures are not supported by the D3D9 backend. + ASSERT(zoffset == 0 && depth == 1); + + GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, type, width, unpackAlignment); + + LoadImageFunction loadFunction = d3d9::GetImageLoadFunction(mInternalFormat); + ASSERT(loadFunction != NULL); + + RECT lockRect = + { + xoffset, yoffset, + xoffset + width, yoffset + height + }; + + D3DLOCKED_RECT locked; + HRESULT result = lock(&locked, &lockRect); + if (FAILED(result)) + { + return; + } + + loadFunction(width, height, depth, + reinterpret_cast(input), inputRowPitch, 0, + reinterpret_cast(locked.pBits), locked.Pitch, 0); + + unlock(); +} + +void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + const void *input) +{ + // 3D textures are not supported by the D3D9 backend. + ASSERT(zoffset == 0 && depth == 1); + + GLsizei inputRowPitch = gl::GetRowPitch(mInternalFormat, GL_UNSIGNED_BYTE, width, 1); + GLsizei inputDepthPitch = gl::GetDepthPitch(mInternalFormat, GL_UNSIGNED_BYTE, width, height, 1); + + ASSERT(xoffset % d3d9::GetBlockWidth(mD3DFormat) == 0); + ASSERT(yoffset % d3d9::GetBlockHeight(mD3DFormat) == 0); + + LoadImageFunction loadFunction = d3d9::GetImageLoadFunction(mInternalFormat); + ASSERT(loadFunction != NULL); + + RECT lockRect = + { + xoffset, yoffset, + xoffset + width, yoffset + height + }; + + D3DLOCKED_RECT locked; + HRESULT result = lock(&locked, &lockRect); + if (FAILED(result)) + { + return; + } + + loadFunction(width, height, depth, + reinterpret_cast(input), inputRowPitch, inputDepthPitch, + reinterpret_cast(locked.pBits), locked.Pitch, 0); + + unlock(); +} + +// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures +void Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) +{ + // ES3.0 only behaviour to copy into a 3d texture + ASSERT(zoffset == 0); + + RenderTarget9 *renderTarget = NULL; + IDirect3DSurface9 *surface = NULL; + gl::FramebufferAttachment *colorbuffer = source->getColorbuffer(0); + + if (colorbuffer) + { + renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); + } + + if (renderTarget) + { + surface = renderTarget->getSurface(); + } + + if (!surface) + { + ERR("Failed to retrieve the render target."); + return gl::error(GL_OUT_OF_MEMORY); + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + IDirect3DSurface9 *renderTargetData = NULL; + D3DSURFACE_DESC description; + surface->GetDesc(&description); + + HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL); + + if (FAILED(result)) + { + ERR("Could not create matching destination surface."); + SafeRelease(surface); + return gl::error(GL_OUT_OF_MEMORY); + } + + result = device->GetRenderTargetData(surface, renderTargetData); + + if (FAILED(result)) + { + ERR("GetRenderTargetData unexpectedly failed."); + SafeRelease(renderTargetData); + SafeRelease(surface); + return gl::error(GL_OUT_OF_MEMORY); + } + + RECT sourceRect = {x, y, x + width, y + height}; + RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height}; + + D3DLOCKED_RECT sourceLock = {0}; + result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0); + + if (FAILED(result)) + { + ERR("Failed to lock the source surface (rectangle might be invalid)."); + SafeRelease(renderTargetData); + SafeRelease(surface); + return gl::error(GL_OUT_OF_MEMORY); + } + + D3DLOCKED_RECT destLock = {0}; + result = lock(&destLock, &destRect); + + if (FAILED(result)) + { + ERR("Failed to lock the destination surface (rectangle might be invalid)."); + renderTargetData->UnlockRect(); + SafeRelease(renderTargetData); + SafeRelease(surface); + return gl::error(GL_OUT_OF_MEMORY); + } + + if (destLock.pBits && sourceLock.pBits) + { + unsigned char *source = (unsigned char*)sourceLock.pBits; + unsigned char *dest = (unsigned char*)destLock.pBits; + + switch (description.Format) + { + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + switch(getD3DFormat()) + { + case D3DFMT_X8R8G8B8: + case D3DFMT_A8R8G8B8: + for(int y = 0; y < height; y++) + { + memcpy(dest, source, 4 * width); + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + dest[x] = source[x * 4 + 2]; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_A8L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + dest[x * 2 + 0] = source[x * 4 + 2]; + dest[x * 2 + 1] = source[x * 4 + 3]; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + case D3DFMT_R5G6B5: + switch(getD3DFormat()) + { + case D3DFMT_X8R8G8B8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned short rgb = ((unsigned short*)source)[x]; + unsigned char red = (rgb & 0xF800) >> 8; + unsigned char green = (rgb & 0x07E0) >> 3; + unsigned char blue = (rgb & 0x001F) << 3; + dest[x + 0] = blue | (blue >> 5); + dest[x + 1] = green | (green >> 6); + dest[x + 2] = red | (red >> 5); + dest[x + 3] = 0xFF; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned char red = source[x * 2 + 1] & 0xF8; + dest[x] = red | (red >> 5); + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + case D3DFMT_A1R5G5B5: + switch(getD3DFormat()) + { + case D3DFMT_X8R8G8B8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned short argb = ((unsigned short*)source)[x]; + unsigned char red = (argb & 0x7C00) >> 7; + unsigned char green = (argb & 0x03E0) >> 2; + unsigned char blue = (argb & 0x001F) << 3; + dest[x + 0] = blue | (blue >> 5); + dest[x + 1] = green | (green >> 5); + dest[x + 2] = red | (red >> 5); + dest[x + 3] = 0xFF; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_A8R8G8B8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned short argb = ((unsigned short*)source)[x]; + unsigned char red = (argb & 0x7C00) >> 7; + unsigned char green = (argb & 0x03E0) >> 2; + unsigned char blue = (argb & 0x001F) << 3; + unsigned char alpha = (signed short)argb >> 15; + dest[x + 0] = blue | (blue >> 5); + dest[x + 1] = green | (green >> 5); + dest[x + 2] = red | (red >> 5); + dest[x + 3] = alpha; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned char red = source[x * 2 + 1] & 0x7C; + dest[x] = (red << 1) | (red >> 4); + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + case D3DFMT_A8L8: + for(int y = 0; y < height; y++) + { + for(int x = 0; x < width; x++) + { + unsigned char red = source[x * 2 + 1] & 0x7C; + dest[x * 2 + 0] = (red << 1) | (red >> 4); + dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7; + } + + source += sourceLock.Pitch; + dest += destLock.Pitch; + } + break; + default: + UNREACHABLE(); + } + break; + default: + UNREACHABLE(); + } + } + + unlock(); + renderTargetData->UnlockRect(); + + SafeRelease(renderTargetData); + SafeRelease(surface); + + mDirty = true; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h new file mode 100644 index 0000000000..2d1536f24b --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h @@ -0,0 +1,80 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Image9.h: Defines the rx::Image9 class, which acts as the interface to +// the actual underlying surfaces of a Texture. + +#ifndef LIBGLESV2_RENDERER_IMAGE9_H_ +#define LIBGLESV2_RENDERER_IMAGE9_H_ + +#include "libGLESv2/renderer/d3d/ImageD3D.h" +#include "common/debug.h" + +namespace gl +{ +class Framebuffer; +} + +namespace rx +{ +class Renderer; +class Renderer9; +class TextureStorageInterface2D; +class TextureStorageInterfaceCube; + +class Image9 : public ImageD3D +{ + public: + Image9(); + ~Image9(); + + static Image9 *makeImage9(Image *img); + + static void generateMipmap(Image9 *dest, Image9 *source); + static void generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface); + static void copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source); + + virtual bool redefine(Renderer *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease); + + D3DFORMAT getD3DFormat() const; + + 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 loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + GLint unpackAlignment, GLenum type, const void *input); + virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, + const void *input); + + virtual void copy(GLint xoffset, GLint yoffset, GLint zoffset,GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); + + private: + DISALLOW_COPY_AND_ASSIGN(Image9); + + void createSurface(); + void setManagedSurface(IDirect3DSurface9 *surface); + bool copyToSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); + + HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect); + void unlock(); + + Renderer9 *mRenderer; + + D3DPOOL mD3DPool; // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable. + D3DFORMAT mD3DFormat; + + IDirect3DSurface9 *mSurface; +}; +} + +#endif // LIBGLESV2_RENDERER_IMAGE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp new file mode 100644 index 0000000000..472e6981a8 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp @@ -0,0 +1,199 @@ +#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 +// found in the LICENSE file. +// + +// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation. + +#include "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ + +IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer) +{ + mIndexBuffer = NULL; + mBufferSize = 0; + mIndexType = 0; + mDynamic = false; +} + +IndexBuffer9::~IndexBuffer9() +{ + SafeRelease(mIndexBuffer); +} + +bool IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) +{ + SafeRelease(mIndexBuffer); + + updateSerial(); + + if (bufferSize > 0) + { + D3DFORMAT format; + if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE) + { + format = D3DFMT_INDEX16; + } + else if (indexType == GL_UNSIGNED_INT) + { + if (mRenderer->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; + } + + DWORD usageFlags = D3DUSAGE_WRITEONLY; + if (dynamic) + { + usageFlags |= D3DUSAGE_DYNAMIC; + } + + HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer); + if (FAILED(result)) + { + ERR("Failed to create an index buffer of size %u, result: 0x%08x.", mBufferSize, result); + return false; + } + } + + mBufferSize = bufferSize; + mIndexType = indexType; + mDynamic = dynamic; + + return true; +} + +IndexBuffer9 *IndexBuffer9::makeIndexBuffer9(IndexBuffer *indexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer9*, indexBuffer)); + return static_cast(indexBuffer); +} + +bool IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) +{ + if (mIndexBuffer) + { + DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0; + + void *mapPtr = NULL; + HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags); + if (FAILED(result)) + { + ERR("Index buffer lock failed with error 0x%08x", result); + return false; + } + + *outMappedMemory = mapPtr; + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +bool IndexBuffer9::unmapBuffer() +{ + if (mIndexBuffer) + { + HRESULT result = mIndexBuffer->Unlock(); + if (FAILED(result)) + { + ERR("Index buffer unlock failed with error 0x%08x", result); + return false; + } + + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +GLenum IndexBuffer9::getIndexType() const +{ + return mIndexType; +} + +unsigned int IndexBuffer9::getBufferSize() const +{ + return mBufferSize; +} + +bool IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType) +{ + if (bufferSize > mBufferSize || indexType != mIndexType) + { + return initialize(bufferSize, indexType, mDynamic); + } + else + { + return true; + } +} + +bool IndexBuffer9::discard() +{ + if (mIndexBuffer) + { + void *dummy; + HRESULT result; + + result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); + if (FAILED(result)) + { + ERR("Discard lock failed with error 0x%08x", result); + return false; + } + + result = mIndexBuffer->Unlock(); + if (FAILED(result)) + { + ERR("Discard unlock failed with error 0x%08x", result); + return false; + } + + return true; + } + else + { + ERR("Index buffer not initialized."); + return false; + } +} + +D3DFORMAT IndexBuffer9::getIndexFormat() const +{ + switch (mIndexType) + { + case GL_UNSIGNED_BYTE: return D3DFMT_INDEX16; + case GL_UNSIGNED_SHORT: return D3DFMT_INDEX16; + case GL_UNSIGNED_INT: return D3DFMT_INDEX32; + default: UNREACHABLE(); return D3DFMT_UNKNOWN; + } +} + +IDirect3DIndexBuffer9 * IndexBuffer9::getBuffer() const +{ + return mIndexBuffer; +} + +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h new file mode 100644 index 0000000000..cfc20e1c64 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h @@ -0,0 +1,53 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Indexffer9.h: Defines the D3D9 IndexBuffer implementation. + +#ifndef LIBGLESV2_RENDERER_INDEXBUFFER9_H_ +#define LIBGLESV2_RENDERER_INDEXBUFFER9_H_ + +#include "libGLESv2/renderer/d3d/IndexBuffer.h" + +namespace rx +{ +class Renderer9; + +class IndexBuffer9 : public IndexBuffer +{ + public: + explicit IndexBuffer9(Renderer9 *const renderer); + virtual ~IndexBuffer9(); + + virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); + + static IndexBuffer9 *makeIndexBuffer9(IndexBuffer *indexBuffer); + + virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); + virtual bool unmapBuffer(); + + virtual GLenum getIndexType() const; + virtual unsigned int getBufferSize() const; + virtual bool setSize(unsigned int bufferSize, GLenum indexType); + + virtual bool discard(); + + D3DFORMAT getIndexFormat() const; + IDirect3DIndexBuffer9 *getBuffer() const; + + private: + DISALLOW_COPY_AND_ASSIGN(IndexBuffer9); + + rx::Renderer9 *const mRenderer; + + IDirect3DIndexBuffer9 *mIndexBuffer; + unsigned int mBufferSize; + GLenum mIndexType; + bool mDynamic; +}; + +} + +#endif // LIBGLESV2_RENDERER_INDEXBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp new file mode 100644 index 0000000000..3c6f1d0d43 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp @@ -0,0 +1,125 @@ +#include "precompiled.h" +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl. + + +#include "libGLESv2/renderer/d3d/d3d9/Query9.h" +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ + +Query9::Query9(rx::Renderer9 *renderer, GLenum type) : QueryImpl(type) +{ + mRenderer = renderer; + mQuery = NULL; +} + +Query9::~Query9() +{ + SafeRelease(mQuery); +} + +void Query9::begin() +{ + if (mQuery == NULL) + { + if (FAILED(mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery))) + { + return gl::error(GL_OUT_OF_MEMORY); + } + } + + HRESULT result = mQuery->Issue(D3DISSUE_BEGIN); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); +} + +void Query9::end() +{ + ASSERT(mQuery); + + HRESULT result = mQuery->Issue(D3DISSUE_END); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + + mStatus = GL_FALSE; + mResult = GL_FALSE; +} + +GLuint Query9::getResult() +{ + if (mQuery != NULL) + { + while (!testQuery()) + { + Sleep(0); + // explicitly check for device loss + // some drivers seem to return S_FALSE even if the device is lost + // instead of D3DERR_DEVICELOST like they should + if (mRenderer->testDeviceLost(true)) + { + return gl::error(GL_OUT_OF_MEMORY, 0); + } + } + } + + return mResult; +} + +GLboolean Query9::isResultAvailable() +{ + if (mQuery != NULL) + { + testQuery(); + } + + return mStatus; +} + +GLboolean Query9::testQuery() +{ + if (mQuery != NULL && mStatus != GL_TRUE) + { + DWORD numPixels = 0; + + HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH); + if (hres == S_OK) + { + mStatus = GL_TRUE; + + switch (getType()) + { + case GL_ANY_SAMPLES_PASSED_EXT: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: + mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; + break; + default: + ASSERT(false); + } + } + else if (d3d9::isDeviceLostError(hres)) + { + mRenderer->notifyDeviceLost(); + return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); + } + + return mStatus; + } + + return GL_TRUE; // prevent blocking when query is null +} + +bool Query9::isStarted() const +{ + return (mQuery != NULL); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h new file mode 100644 index 0000000000..62906230c4 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h @@ -0,0 +1,41 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Query9.h: Defines the rx::Query9 class which implements rx::QueryImpl. + +#ifndef LIBGLESV2_RENDERER_QUERY9_H_ +#define LIBGLESV2_RENDERER_QUERY9_H_ + +#include "libGLESv2/renderer/QueryImpl.h" + +namespace rx +{ +class Renderer9; + +class Query9 : public QueryImpl +{ + public: + Query9(rx::Renderer9 *renderer, GLenum type); + virtual ~Query9(); + + virtual void begin(); + virtual void end(); + virtual GLuint getResult(); + virtual GLboolean isResultAvailable(); + virtual bool isStarted() const; + + private: + DISALLOW_COPY_AND_ASSIGN(Query9); + + GLboolean testQuery(); + + rx::Renderer9 *mRenderer; + IDirect3DQuery9 *mQuery; +}; + +} + +#endif // LIBGLESV2_RENDERER_QUERY9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp new file mode 100644 index 0000000000..49bd9b4000 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp @@ -0,0 +1,139 @@ +#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 +// found in the LICENSE file. +// + +// RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9 +// pointers retained by renderbuffers. + +#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" + +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/main.h" + +namespace rx +{ + +// TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being given. +RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface) +{ + mRenderer = Renderer9::makeRenderer9(renderer); + mRenderTarget = surface; + + if (mRenderTarget) + { + D3DSURFACE_DESC description; + mRenderTarget->GetDesc(&description); + + mWidth = description.Width; + mHeight = description.Height; + mDepth = 1; + + mInternalFormat = d3d9_gl::GetInternalFormat(description.Format); + mActualFormat = d3d9_gl::GetInternalFormat(description.Format); + mSamples = d3d9_gl::GetSamplesCount(description.MultiSampleType); + } +} + +RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples) +{ + mRenderer = Renderer9::makeRenderer9(renderer); + mRenderTarget = NULL; + + D3DFORMAT renderFormat = gl_d3d9::GetRenderFormat(internalFormat); + int supportedSamples = mRenderer->getNearestSupportedSamples(renderFormat, samples); + + if (supportedSamples == -1) + { + gl::error(GL_OUT_OF_MEMORY); + + return; + } + + HRESULT result = D3DERR_INVALIDCALL; + + if (width > 0 && height > 0) + { + IDirect3DDevice9 *device = mRenderer->getDevice(); + + bool requiresInitialization = false; + + if (gl::GetDepthBits(internalFormat) > 0 || + gl::GetStencilBits(internalFormat) > 0) + { + result = device->CreateDepthStencilSurface(width, height, renderFormat, + gl_d3d9::GetMultisampleType(supportedSamples), + 0, FALSE, &mRenderTarget, NULL); + } + else + { + requiresInitialization = gl_d3d9::RequiresTextureDataInitialization(internalFormat); + + result = device->CreateRenderTarget(width, height, renderFormat, + gl_d3d9::GetMultisampleType(supportedSamples), + 0, FALSE, &mRenderTarget, NULL); + } + + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) + { + gl::error(GL_OUT_OF_MEMORY); + + return; + } + + ASSERT(SUCCEEDED(result)); + + if (requiresInitialization) + { + // This format requires that the data be initialized before the render target can be used + // Unfortunately this requires a Get call on the d3d device but it is far better than having + // to mark the render target as lockable and copy data to the gpu. + IDirect3DSurface9 *prevRenderTarget = NULL; + device->GetRenderTarget(0, &prevRenderTarget); + device->SetRenderTarget(0, mRenderTarget); + device->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_RGBA(0, 0, 0, 255), 0.0f, 0); + device->SetRenderTarget(0, prevRenderTarget); + } + } + + mWidth = width; + mHeight = height; + mDepth = 1; + mInternalFormat = internalFormat; + mSamples = supportedSamples; + mActualFormat = d3d9_gl::GetInternalFormat(renderFormat); +} + +RenderTarget9::~RenderTarget9() +{ + SafeRelease(mRenderTarget); +} + +RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget9*, target)); + return static_cast(target); +} + +void RenderTarget9::invalidate(GLint x, GLint y, GLsizei width, GLsizei height) +{ + // Currently a no-op +} + +IDirect3DSurface9 *RenderTarget9::getSurface() +{ + // Caller is responsible for releasing the returned surface reference. + // TODO: remove the AddRef to match RenderTarget11 + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + + return mRenderTarget; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h new file mode 100644 index 0000000000..68d7adb49e --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h @@ -0,0 +1,43 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// RenderTarget9.h: Defines a D3D9-specific wrapper for IDirect3DSurface9 pointers +// retained by Renderbuffers. + +#ifndef LIBGLESV2_RENDERER_RENDERTARGET9_H_ +#define LIBGLESV2_RENDERER_RENDERTARGET9_H_ + +#include "libGLESv2/renderer/RenderTarget.h" + +namespace rx +{ +class Renderer; +class Renderer9; + +class RenderTarget9 : public RenderTarget +{ + public: + RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface); + RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum internalFormat, GLsizei samples); + virtual ~RenderTarget9(); + + static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget); + + virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height); + + IDirect3DSurface9 *getSurface(); + + private: + DISALLOW_COPY_AND_ASSIGN(RenderTarget9); + + IDirect3DSurface9 *mRenderTarget; + + Renderer9 *mRenderer; +}; + +} + +#endif // LIBGLESV2_RENDERER_RENDERTARGET9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp new file mode 100644 index 0000000000..491c27a6ab --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp @@ -0,0 +1,3254 @@ +#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 +// found in the LICENSE file. +// + +// 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" +#include "libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h" +#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" +#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h" +#include "libGLESv2/renderer/d3d/d3d9/Image9.h" +#include "libGLESv2/renderer/d3d/d3d9/Blit9.h" +#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h" +#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/Buffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/Query9.h" +#include "libGLESv2/renderer/d3d/d3d9/Fence9.h" +#include "libGLESv2/renderer/d3d/d3d9/VertexArray9.h" +#include "libGLESv2/angletypes.h" + +#include "libEGL/Display.h" + +#include "third_party/trace_event/trace_event.h" + +// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros +#define REF_RAST 0 + +// The "Debug This Pixel..." feature in PIX often fails when using the +// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7 +// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file. +#if !defined(ANGLE_ENABLE_D3D9EX) +// Enables use of the IDirect3D9Ex interface, when available +#define ANGLE_ENABLE_D3D9EX 1 +#endif // !defined(ANGLE_ENABLE_D3D9EX) + +#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL) +#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL3 +#endif + +const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z'))); +const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L'))); + +namespace rx +{ +static const D3DFORMAT RenderTargetFormats[] = + { + D3DFMT_A1R5G5B5, + // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value. + D3DFMT_A8R8G8B8, + D3DFMT_R5G6B5, + // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format + D3DFMT_X8R8G8B8 + }; + +static const D3DFORMAT DepthStencilFormats[] = + { + D3DFMT_UNKNOWN, + // D3DFMT_D16_LOCKABLE, + D3DFMT_D32, + // D3DFMT_D15S1, + D3DFMT_D24S8, + D3DFMT_D24X8, + // D3DFMT_D24X4S4, + D3DFMT_D16, + // D3DFMT_D32F_LOCKABLE, + // D3DFMT_D24FS8 + }; + +enum +{ + MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256, + MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32, + MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224, + MAX_VARYING_VECTORS_SM2 = 8, + MAX_VARYING_VECTORS_SM3 = 10, + + MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4 +}; + +Renderer9::Renderer9(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay) + : Renderer(display), + mDc(hDc) +{ + mD3d9Module = NULL; + + mD3d9 = NULL; + mD3d9Ex = NULL; + mDevice = NULL; + mDeviceEx = NULL; + mDeviceWindow = NULL; + mBlit = NULL; + + mAdapter = D3DADAPTER_DEFAULT; + + #if REF_RAST == 1 || defined(FORCE_REF_RAST) + mDeviceType = D3DDEVTYPE_REF; + #else + mDeviceType = D3DDEVTYPE_HAL; + #endif + + mDeviceLost = false; + + mMaxSupportedSamples = 0; + + mMaskedClearSavedState = NULL; + + mVertexDataManager = NULL; + mIndexDataManager = NULL; + mLineLoopIB = NULL; + + mMaxNullColorbufferLRU = 0; + for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + mNullColorbufferCache[i].lruCount = 0; + mNullColorbufferCache[i].width = 0; + mNullColorbufferCache[i].height = 0; + mNullColorbufferCache[i].buffer = NULL; + } + + mAppliedVertexShader = NULL; + mAppliedPixelShader = NULL; + mAppliedProgramSerial = 0; +} + +Renderer9::~Renderer9() +{ + if (mDevice) + { + // If the device is lost, reset it first to prevent leaving the driver in an unstable state + if (testDeviceLost(false)) + { + resetDevice(); + } + } + + release(); +} + +void Renderer9::release() +{ + releaseDeviceResources(); + + SafeRelease(mDevice); + SafeRelease(mDeviceEx); + SafeRelease(mD3d9); + SafeRelease(mD3d9Ex); + + mCompiler.release(); + + if (mDeviceWindow) + { + DestroyWindow(mDeviceWindow); + mDeviceWindow = NULL; + } + + mD3d9Module = NULL; +} + +Renderer9 *Renderer9::makeRenderer9(Renderer *renderer) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer9*, renderer)); + return static_cast(renderer); +} + +EGLint Renderer9::initialize() +{ + if (!mCompiler.initialize()) + { + return EGL_NOT_INITIALIZED; + } + + TRACE_EVENT0("gpu", "GetModuleHandle_d3d9"); + mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); + + if (mD3d9Module == NULL) + { + ERR("No D3D9 module found - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); + Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); + + // Use Direct3D9Ex if available. Among other things, this version is less + // inclined to report a lost context, for example when the user switches + // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. + if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) + { + TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface"); + ASSERT(mD3d9Ex); + mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast(&mD3d9)); + ASSERT(mD3d9); + } + else + { + TRACE_EVENT0("gpu", "Direct3DCreate9"); + mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); + } + + if (!mD3d9) + { + ERR("Could not create D3D9 device - aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + if (mDc != NULL) + { + // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to + } + + HRESULT result; + + // Give up on getting device caps after about one second. + { + TRACE_EVENT0("gpu", "GetDeviceCaps"); + for (int i = 0; i < 10; ++i) + { + result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); + if (SUCCEEDED(result)) + { + break; + } + else if (result == D3DERR_NOTAVAILABLE) + { + Sleep(100); // Give the driver some time to initialize/recover + } + else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from + { + ERR("failed to get device caps (0x%x)\n", result); + return EGL_NOT_INITIALIZED; + } + } + } + + if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0)) + { + ERR("Renderer does not support PS 2.0. aborting!\n"); + return EGL_NOT_INITIALIZED; + } + + // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported. + // This is required by Texture2D::ensureRenderTarget. + if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0) + { + ERR("Renderer does not support stretctrect from textures!\n"); + return EGL_NOT_INITIALIZED; + } + + { + TRACE_EVENT0("gpu", "GetAdapterIdentifier"); + mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); + } + + mMinSwapInterval = 4; + mMaxSwapInterval = 0; + + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) + { + mMinSwapInterval = std::min(mMinSwapInterval, 0); + mMaxSwapInterval = std::max(mMaxSwapInterval, 0); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) + { + mMinSwapInterval = std::min(mMinSwapInterval, 1); + mMaxSwapInterval = std::max(mMaxSwapInterval, 1); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) + { + mMinSwapInterval = std::min(mMinSwapInterval, 2); + mMaxSwapInterval = std::max(mMaxSwapInterval, 2); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) + { + mMinSwapInterval = std::min(mMinSwapInterval, 3); + mMaxSwapInterval = std::max(mMaxSwapInterval, 3); + } + if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) + { + mMinSwapInterval = std::min(mMinSwapInterval, 4); + mMaxSwapInterval = std::max(mMaxSwapInterval, 4); + } + + 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); + } + + D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); + DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; + + { + TRACE_EVENT0("gpu", "D3d9_CreateDevice"); + result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); + } + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) + { + return EGL_BAD_ALLOC; + } + + if (FAILED(result)) + { + TRACE_EVENT0("gpu", "D3d9_CreateDevice2"); + result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST); + return EGL_BAD_ALLOC; + } + } + + if (mD3d9Ex) + { + TRACE_EVENT0("gpu", "mDevice_QueryInterface"); + result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**)&mDeviceEx); + ASSERT(SUCCEEDED(result)); + } + + { + TRACE_EVENT0("gpu", "ShaderCache initialize"); + mVertexShaderCache.initialize(mDevice); + mPixelShaderCache.initialize(mDevice); + } + + D3DDISPLAYMODE currentDisplayMode; + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); + + // Check vertex texture support + // Only Direct3D 10 ready devices support all the necessary vertex texture formats. + // We test this using D3D9 by checking support for the R16F format. + mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) && + SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, + D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F)); + + initializeDevice(); + + d3d9::InitializeVertexTranslations(this); + + return EGL_SUCCESS; +} + +// do any one-time device initialization +// NOTE: this is also needed after a device lost/reset +// to reset the scene status and ensure the default states are reset. +void Renderer9::initializeDevice() +{ + // Permanent non-default states + mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); + mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE); + + if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) + { + mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize); + } + else + { + mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f + } + + markAllStateDirty(); + + mSceneStarted = false; + + ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager); + mBlit = new Blit9(this); + mVertexDataManager = new rx::VertexDataManager(this); + mIndexDataManager = new rx::IndexDataManager(this); +} + +D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters() +{ + D3DPRESENT_PARAMETERS presentParameters = {0}; + + // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters. + presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN; + presentParameters.BackBufferCount = 1; + presentParameters.BackBufferFormat = D3DFMT_UNKNOWN; + presentParameters.BackBufferWidth = 1; + presentParameters.BackBufferHeight = 1; + presentParameters.EnableAutoDepthStencil = FALSE; + presentParameters.Flags = 0; + presentParameters.hDeviceWindow = mDeviceWindow; + presentParameters.MultiSampleQuality = 0; + presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; + presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + presentParameters.Windowed = TRUE; + + return presentParameters; +} + +int Renderer9::generateConfigs(ConfigDesc **configDescList) +{ + D3DDISPLAYMODE currentDisplayMode; + mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); + + unsigned int numRenderFormats = ArraySize(RenderTargetFormats); + unsigned int numDepthFormats = ArraySize(DepthStencilFormats); + (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; + int numConfigs = 0; + + for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) + { + D3DFORMAT renderTargetFormat = RenderTargetFormats[formatIndex]; + + HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat); + + if (SUCCEEDED(result)) + { + for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) + { + D3DFORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; + HRESULT result = D3D_OK; + + if(depthStencilFormat != D3DFMT_UNKNOWN) + { + result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat); + } + + if (SUCCEEDED(result)) + { + if(depthStencilFormat != D3DFMT_UNKNOWN) + { + result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat); + } + + if (SUCCEEDED(result)) + { + ConfigDesc newConfig; + newConfig.renderTargetFormat = d3d9_gl::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; + } + } + } + } + } + + return numConfigs; +} + +void Renderer9::deleteConfigs(ConfigDesc *configDescList) +{ + delete [] (configDescList); +} + +void Renderer9::startScene() +{ + if (!mSceneStarted) + { + long result = mDevice->BeginScene(); + if (SUCCEEDED(result)) { + // This is defensive checking against the device being + // lost at unexpected times. + mSceneStarted = true; + } + } +} + +void Renderer9::endScene() +{ + if (mSceneStarted) + { + // EndScene can fail if the device was lost, for example due + // to a TDR during a draw call. + mDevice->EndScene(); + mSceneStarted = false; + } +} + +void Renderer9::sync(bool block) +{ + HRESULT result; + + IDirect3DQuery9* query = allocateEventQuery(); + if (!query) + { + return; + } + + result = query->Issue(D3DISSUE_END); + ASSERT(SUCCEEDED(result)); + + do + { + result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); + + if(block && result == S_FALSE) + { + // Keep polling, but allow other threads to do something useful first + Sleep(0); + // explicitly check for device loss + // some drivers seem to return S_FALSE even if the device is lost + // instead of D3DERR_DEVICELOST like they should + if (testDeviceLost(false)) + { + result = D3DERR_DEVICELOST; + } + } + } + while(block && result == S_FALSE); + + freeEventQuery(query); + + if (d3d9::isDeviceLostError(result)) + { + notifyDeviceLost(); + } +} + +SwapChain *Renderer9::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) +{ + return new rx::SwapChain9(this, window, shareHandle, backBufferFormat, depthBufferFormat); +} + +IDirect3DQuery9* Renderer9::allocateEventQuery() +{ + IDirect3DQuery9 *query = NULL; + + if (mEventQueryPool.empty()) + { + HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + } + else + { + query = mEventQueryPool.back(); + mEventQueryPool.pop_back(); + } + + return query; +} + +void Renderer9::freeEventQuery(IDirect3DQuery9* query) +{ + if (mEventQueryPool.size() > 1000) + { + SafeRelease(query); + } + else + { + mEventQueryPool.push_back(query); + } +} + +IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length) +{ + return mVertexShaderCache.create(function, length); +} + +IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length) +{ + return mPixelShaderCache.create(function, length); +} + +HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer) +{ + D3DPOOL Pool = getBufferPool(Usage); + return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL); +} + +VertexBuffer *Renderer9::createVertexBuffer() +{ + return new VertexBuffer9(this); +} + +HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer) +{ + D3DPOOL Pool = getBufferPool(Usage); + return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL); +} + +IndexBuffer *Renderer9::createIndexBuffer() +{ + return new IndexBuffer9(this); +} + +BufferImpl *Renderer9::createBuffer() +{ + return new Buffer9(this); +} + +VertexArrayImpl *Renderer9::createVertexArray() +{ + return new VertexArray9(this); +} + +QueryImpl *Renderer9::createQuery(GLenum type) +{ + return new Query9(this, type); +} + +FenceImpl *Renderer9::createFence() +{ + return new Fence9(this); +} + +bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const +{ + // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3. + return false; +} + +bool Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) +{ + // Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3. + UNREACHABLE(); + return false; +} + +void Renderer9::generateSwizzle(gl::Texture *texture) +{ + // Swizzled textures are not available in ES2 or D3D9 + UNREACHABLE(); +} + +void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) +{ + bool *forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates; + gl::SamplerState *appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates; + + if (forceSetSamplers[index] || memcmp(&samplerState, &appliedSamplers[index], sizeof(gl::SamplerState)) != 0) + { + int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; + int d3dSampler = index + d3dSamplerOffset; + + mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS)); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT)); + + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy)); + D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter; + gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.baseLevel); + if (getRendererExtensions().textureFilterAnisotropic) + { + mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy); + } + } + + forceSetSamplers[index] = false; + appliedSamplers[index] = samplerState; +} + +void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture) +{ + int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; + int d3dSampler = index + d3dSamplerOffset; + IDirect3DBaseTexture9 *d3dTexture = NULL; + unsigned int serial = 0; + bool forceSetTexture = false; + + unsigned int *appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials; + + if (texture) + { + TextureStorageInterface *texStorage = texture->getNativeTexture(); + if (texStorage) + { + TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage->getStorageInstance()); + d3dTexture = storage9->getBaseTexture(); + } + // If we get NULL back from getBaseTexture here, something went wrong + // in the texture class and we're unexpectedly missing the d3d texture + ASSERT(d3dTexture != NULL); + + serial = texture->getTextureSerial(); + forceSetTexture = texture->hasDirtyImages(); + } + + if (forceSetTexture || appliedSerials[index] != serial) + { + mDevice->SetTexture(d3dSampler, d3dTexture); + } + + appliedSerials[index] = serial; +} + +bool Renderer9::setUniformBuffers(const gl::Buffer* /*vertexUniformBuffers*/[], const gl::Buffer* /*fragmentUniformBuffers*/[]) +{ + // No effect in ES2/D3D9 + return true; +} + +void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState) +{ + bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0; + + if (rasterStateChanged) + { + // Set the cull mode + if (rasterState.cullFace) + { + mDevice->SetRenderState(D3DRS_CULLMODE, gl_d3d9::ConvertCullMode(rasterState.cullMode, rasterState.frontFace)); + } + else + { + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + } + + if (rasterState.polygonOffsetFill) + { + if (mCurDepthSize > 0) + { + mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&rasterState.polygonOffsetFactor); + + float depthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast(mCurDepthSize)); + mDevice->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&depthBias); + } + } + else + { + mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); + mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0); + } + + mCurRasterState = rasterState; + } + + mForceSetRasterState = false; +} + +void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor, + unsigned int sampleMask) +{ + bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0; + bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::ColorF)) != 0; + bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask; + + if (blendStateChanged || blendColorChanged) + { + if (blendState.blend) + { + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + + if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && + blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) + { + mDevice->SetRenderState(D3DRS_BLENDFACTOR, gl_d3d9::ConvertColor(blendColor)); + } + else + { + mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), + gl::unorm<8>(blendColor.alpha), + gl::unorm<8>(blendColor.alpha), + gl::unorm<8>(blendColor.alpha))); + } + + mDevice->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB)); + mDevice->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB)); + mDevice->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB)); + + if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha || + blendState.destBlendRGB != blendState.destBlendAlpha || + blendState.blendEquationRGB != blendState.blendEquationAlpha) + { + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + + mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha)); + mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha)); + mDevice->SetRenderState(D3DRS_BLENDOPALPHA, gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha)); + } + else + { + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); + } + } + else + { + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + } + + if (blendState.sampleAlphaToCoverage) + { + FIXME("Sample alpha to coverage is unimplemented."); + } + + gl::FramebufferAttachment *attachment = framebuffer->getFirstColorbuffer(); + GLenum internalFormat = attachment ? attachment->getInternalFormat() : GL_NONE; + + // Set the color mask + bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD; + // Apparently some ATI cards have a bug where a draw with a zero color + // write mask can cause later draws to have incorrect results. Instead, + // set a nonzero color write mask but modify the blend state so that no + // drawing is done. + // http://code.google.com/p/angleproject/issues/detail?id=169 + + 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); + if (colorMask == 0 && !zeroColorMaskAllowed) + { + // Enable green channel, but set blending so nothing will be drawn. + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN); + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); + + mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); + mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); + mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + } + else + { + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask); + } + + mDevice->SetRenderState(D3DRS_DITHERENABLE, blendState.dither ? TRUE : FALSE); + + mCurBlendState = blendState; + mCurBlendColor = blendColor; + } + + if (sampleMaskChanged) + { + // Set the multisample mask + mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); + mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast(sampleMask)); + + mCurSampleMask = sampleMask; + } + + mForceSetBlendState = false; +} + +void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, + int stencilBackRef, bool frontFaceCCW) +{ + bool depthStencilStateChanged = mForceSetDepthStencilState || + memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0; + bool stencilRefChanged = mForceSetDepthStencilState || stencilRef != mCurStencilRef || + stencilBackRef != mCurStencilBackRef; + bool frontFaceCCWChanged = mForceSetDepthStencilState || frontFaceCCW != mCurFrontFaceCCW; + + if (depthStencilStateChanged) + { + if (depthStencilState.depthTest) + { + mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); + mDevice->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthStencilState.depthFunc)); + } + else + { + mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + } + + mCurDepthStencilState = depthStencilState; + } + + if (depthStencilStateChanged || stencilRefChanged || frontFaceCCWChanged) + { + if (depthStencilState.stencilTest && mCurStencilSize > 0) + { + mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); + mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE); + + // FIXME: Unsupported by D3D9 + const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; + const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; + const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; + + ASSERT(depthStencilState.stencilWritemask == depthStencilState.stencilBackWritemask); + ASSERT(stencilRef == stencilBackRef); + ASSERT(depthStencilState.stencilMask == depthStencilState.stencilBackMask); + + // get the maximum size of the stencil ref + unsigned int maxStencil = (1 << mCurStencilSize) - 1; + + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, + depthStencilState.stencilWritemask); + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, + gl_d3d9::ConvertComparison(depthStencilState.stencilFunc)); + + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, + (stencilRef < (int)maxStencil) ? stencilRef : maxStencil); + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, + depthStencilState.stencilMask); + + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilFail)); + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthFail)); + mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthPass)); + + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, + depthStencilState.stencilBackWritemask); + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, + gl_d3d9::ConvertComparison(depthStencilState.stencilBackFunc)); + + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, + (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil); + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, + depthStencilState.stencilBackMask); + + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackFail)); + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthFail)); + mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, + gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthPass)); + } + else + { + mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); + } + + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, depthStencilState.depthMask ? TRUE : FALSE); + + mCurStencilRef = stencilRef; + mCurStencilBackRef = stencilBackRef; + mCurFrontFaceCCW = frontFaceCCW; + } + + mForceSetDepthStencilState = false; +} + +void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) +{ + bool scissorChanged = mForceSetScissor || + memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || + enabled != mScissorEnabled; + + if (scissorChanged) + { + if (enabled) + { + RECT rect; + rect.left = gl::clamp(scissor.x, 0, static_cast(mRenderTargetDesc.width)); + rect.top = gl::clamp(scissor.y, 0, static_cast(mRenderTargetDesc.height)); + rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast(mRenderTargetDesc.width)); + rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast(mRenderTargetDesc.height)); + mDevice->SetScissorRect(&rect); + } + + mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, enabled ? TRUE : FALSE); + + mScissorEnabled = enabled; + mCurScissor = scissor; + } + + mForceSetScissor = false; +} + +bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport) +{ + gl::Rectangle actualViewport = viewport; + float actualZNear = gl::clamp01(zNear); + float actualZFar = gl::clamp01(zFar); + if (ignoreViewport) + { + actualViewport.x = 0; + actualViewport.y = 0; + actualViewport.width = mRenderTargetDesc.width; + actualViewport.height = mRenderTargetDesc.height; + actualZNear = 0.0f; + actualZFar = 1.0f; + } + + D3DVIEWPORT9 dxViewport; + dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast(mRenderTargetDesc.width)); + dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast(mRenderTargetDesc.height)); + dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast(mRenderTargetDesc.width) - static_cast(dxViewport.X)); + dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast(mRenderTargetDesc.height) - static_cast(dxViewport.Y)); + dxViewport.MinZ = actualZNear; + dxViewport.MaxZ = actualZFar; + + if (dxViewport.Width <= 0 || dxViewport.Height <= 0) + { + return false; // Nothing to render + } + + float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f); + + bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || + actualZNear != mCurNear || actualZFar != mCurFar || mCurDepthFront != depthFront; + if (viewportChanged) + { + mDevice->SetViewport(&dxViewport); + + mCurViewport = actualViewport; + mCurNear = actualZNear; + mCurFar = actualZFar; + mCurDepthFront = depthFront; + + dx_VertexConstants vc = {0}; + dx_PixelConstants pc = {0}; + + vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width; + vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height; + vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width; + vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height; + + pc.viewCoords[0] = actualViewport.width * 0.5f; + pc.viewCoords[1] = actualViewport.height * 0.5f; + pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); + pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); + + pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f; + pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f; + pc.depthFront[2] = depthFront; + + vc.depthRange[0] = actualZNear; + vc.depthRange[1] = actualZFar; + vc.depthRange[2] = actualZFar - actualZNear; + + pc.depthRange[0] = actualZNear; + pc.depthRange[1] = actualZFar; + pc.depthRange[2] = actualZFar - actualZNear; + + if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0) + { + mVertexConstants = vc; + mDxUniformsDirty = true; + } + + if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0) + { + mPixelConstants = pc; + mDxUniformsDirty = true; + } + } + + mForceSetViewport = false; + return true; +} + +bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count) +{ + switch (mode) + { + case GL_POINTS: + mPrimitiveType = D3DPT_POINTLIST; + mPrimitiveCount = count; + break; + case GL_LINES: + mPrimitiveType = D3DPT_LINELIST; + mPrimitiveCount = count / 2; + break; + case GL_LINE_LOOP: + mPrimitiveType = D3DPT_LINESTRIP; + mPrimitiveCount = count - 1; // D3D doesn't support line loops, so we draw the last line separately + break; + case GL_LINE_STRIP: + mPrimitiveType = D3DPT_LINESTRIP; + mPrimitiveCount = count - 1; + break; + case GL_TRIANGLES: + mPrimitiveType = D3DPT_TRIANGLELIST; + mPrimitiveCount = count / 3; + break; + case GL_TRIANGLE_STRIP: + mPrimitiveType = D3DPT_TRIANGLESTRIP; + mPrimitiveCount = count - 2; + break; + case GL_TRIANGLE_FAN: + mPrimitiveType = D3DPT_TRIANGLEFAN; + mPrimitiveCount = count - 2; + break; + default: + UNREACHABLE(); + return false; + } + + return mPrimitiveCount > 0; +} + + +gl::FramebufferAttachment *Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer) +{ + if (!depthbuffer) + { + ERR("Unexpected null depthbuffer for depth-only FBO."); + return NULL; + } + + GLsizei width = depthbuffer->getWidth(); + GLsizei height = depthbuffer->getHeight(); + + // search cached nullcolorbuffers + for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + if (mNullColorbufferCache[i].buffer != NULL && + mNullColorbufferCache[i].width == width && + mNullColorbufferCache[i].height == height) + { + mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU; + return mNullColorbufferCache[i].buffer; + } + } + + gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(0, new gl::Colorbuffer(this, width, height, GL_NONE, 0)); + gl::RenderbufferAttachment *nullbuffer = new gl::RenderbufferAttachment(nullRenderbuffer); + + // add nullbuffer to the cache + NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0]; + for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + if (mNullColorbufferCache[i].lruCount < oldest->lruCount) + { + oldest = &mNullColorbufferCache[i]; + } + } + + delete oldest->buffer; + oldest->buffer = nullbuffer; + oldest->lruCount = ++mMaxNullColorbufferLRU; + oldest->width = width; + oldest->height = height; + + return nullbuffer; +} + +bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) +{ + // if there is no color attachment we must synthesize a NULL colorattachment + // to keep the D3D runtime happy. This should only be possible if depth texturing. + gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(0); + if (!attachment) + { + attachment = getNullColorbuffer(framebuffer->getDepthbuffer()); + } + if (!attachment) + { + ERR("unable to locate renderbuffer for FBO."); + return false; + } + + bool renderTargetChanged = false; + unsigned int renderTargetSerial = attachment->getSerial(); + if (renderTargetSerial != mAppliedRenderTargetSerial) + { + // Apply the render target on the device + IDirect3DSurface9 *renderTargetSurface = NULL; + + RenderTarget *renderTarget = attachment->getRenderTarget(); + if (renderTarget) + { + renderTargetSurface = RenderTarget9::makeRenderTarget9(renderTarget)->getSurface(); + } + + if (!renderTargetSurface) + { + ERR("render target pointer unexpectedly null."); + return false; // Context must be lost + } + + mDevice->SetRenderTarget(0, renderTargetSurface); + SafeRelease(renderTargetSurface); + + mAppliedRenderTargetSerial = renderTargetSerial; + renderTargetChanged = true; + } + + gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer(); + unsigned int depthbufferSerial = 0; + unsigned int stencilbufferSerial = 0; + if (depthStencil) + { + depthbufferSerial = depthStencil->getSerial(); + } + else if (framebuffer->getStencilbuffer()) + { + depthStencil = framebuffer->getStencilbuffer(); + stencilbufferSerial = depthStencil->getSerial(); + } + + if (depthbufferSerial != mAppliedDepthbufferSerial || + stencilbufferSerial != mAppliedStencilbufferSerial || + !mDepthStencilInitialized) + { + unsigned int depthSize = 0; + unsigned int stencilSize = 0; + + // Apply the depth stencil on the device + if (depthStencil) + { + IDirect3DSurface9 *depthStencilSurface = NULL; + RenderTarget *depthStencilRenderTarget = depthStencil->getDepthStencil(); + + if (depthStencilRenderTarget) + { + depthStencilSurface = RenderTarget9::makeRenderTarget9(depthStencilRenderTarget)->getSurface(); + } + + if (!depthStencilSurface) + { + ERR("depth stencil pointer unexpectedly null."); + return false; // Context must be lost + } + + mDevice->SetDepthStencilSurface(depthStencilSurface); + SafeRelease(depthStencilSurface); + + depthSize = depthStencil->getDepthSize(); + stencilSize = depthStencil->getStencilSize(); + } + else + { + mDevice->SetDepthStencilSurface(NULL); + } + + if (!mDepthStencilInitialized || depthSize != mCurDepthSize) + { + mCurDepthSize = depthSize; + mForceSetRasterState = true; + } + + if (!mDepthStencilInitialized || stencilSize != mCurStencilSize) + { + mCurStencilSize = stencilSize; + mForceSetDepthStencilState = true; + } + + mAppliedDepthbufferSerial = depthbufferSerial; + mAppliedStencilbufferSerial = stencilbufferSerial; + mDepthStencilInitialized = true; + } + + if (renderTargetChanged || !mRenderTargetDescInitialized) + { + mForceSetScissor = true; + mForceSetViewport = true; + mForceSetBlendState = true; + + mRenderTargetDesc.width = attachment->getWidth(); + mRenderTargetDesc.height = attachment->getHeight(); + mRenderTargetDesc.format = attachment->getActualFormat(); + mRenderTargetDescInitialized = true; + } + + return true; +} + +GLenum 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) + { + return err; + } + + return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw); +} + +// Applies the indices and element array bindings to the Direct3D 9 device +GLenum Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) +{ + GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); + + if (err == GL_NO_ERROR) + { + // Directly binding the storage buffer is not supported for d3d9 + ASSERT(indexInfo->storage == NULL); + + if (indexInfo->serial != mAppliedIBSerial) + { + IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer); + + mDevice->SetIndices(indexBuffer->getBuffer()); + mAppliedIBSerial = indexInfo->serial; + } + } + + return err; +} + +void Renderer9::applyTransformFeedbackBuffers(gl::Buffer *transformFeedbackBuffers[], GLintptr offsets[]) +{ + UNREACHABLE(); +} + +void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) +{ + ASSERT(!transformFeedbackActive); + + startScene(); + + if (mode == GL_LINE_LOOP) + { + drawLineLoop(count, GL_NONE, NULL, 0, NULL); + } + else if (instances > 0) + { + StaticIndexBufferInterface *countingIB = mIndexDataManager->getCountingIndices(count); + if (countingIB) + { + if (mAppliedIBSerial != countingIB->getSerial()) + { + IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer()); + + mDevice->SetIndices(indexBuffer->getBuffer()); + mAppliedIBSerial = countingIB->getSerial(); + } + + for (int i = 0; i < mRepeatDraw; i++) + { + mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount); + } + } + else + { + ERR("Could not create a counting index buffer for glDrawArraysInstanced."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + else // Regular case + { + mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount); + } +} + +void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, + gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/) +{ + startScene(); + + if (mode == GL_POINTS) + { + drawIndexedPoints(count, type, indices, indexInfo.minIndex, elementArrayBuffer); + } + else if (mode == GL_LINE_LOOP) + { + drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); + } + else + { + for (int i = 0; i < mRepeatDraw; i++) + { + GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; + mDevice->DrawIndexedPrimitive(mPrimitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount); + } + } +} + +void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +{ + // Get the raw indices for an indexed draw + if (type != GL_NONE && elementArrayBuffer) + { + gl::Buffer *indexBuffer = elementArrayBuffer; + BufferImpl *storage = indexBuffer->getImplementation(); + intptr_t offset = reinterpret_cast(indices); + indices = static_cast(storage->getData()) + offset; + } + + unsigned int startIndex = 0; + + if (getRendererExtensions().elementIndexUint) + { + if (!mLineLoopIB) + { + mLineLoopIB = new StreamingIndexBufferInterface(this); + if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) + { + delete mLineLoopIB; + mLineLoopIB = NULL; + + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + // Checked by Renderer9::applyPrimitiveType + ASSERT(count >= 0); + + if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) + { + ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); + return gl::error(GL_OUT_OF_MEMORY); + } + + const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); + if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) + { + ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + void* mappedMemory = NULL; + unsigned int offset = 0; + if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) + { + ERR("Could not map index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + startIndex = static_cast(offset) / 4; + unsigned int *data = reinterpret_cast(mappedMemory); + + switch (type) + { + case GL_NONE: // Non-indexed draw + for (int i = 0; i < count; i++) + { + data[i] = i; + } + data[count] = 0; + break; + case GL_UNSIGNED_BYTE: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_SHORT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_INT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + default: UNREACHABLE(); + } + + if (!mLineLoopIB->unmapBuffer()) + { + ERR("Could not unmap index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + else + { + if (!mLineLoopIB) + { + mLineLoopIB = new StreamingIndexBufferInterface(this); + if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT)) + { + delete mLineLoopIB; + mLineLoopIB = NULL; + + ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + // Checked by Renderer9::applyPrimitiveType + ASSERT(count >= 0); + + if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned short))) + { + ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required."); + return gl::error(GL_OUT_OF_MEMORY); + } + + const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned short); + if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT)) + { + ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + void* mappedMemory = NULL; + unsigned int offset; + if (mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) + { + ERR("Could not map index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + + startIndex = static_cast(offset) / 2; + unsigned short *data = reinterpret_cast(mappedMemory); + + switch (type) + { + case GL_NONE: // Non-indexed draw + for (int i = 0; i < count; i++) + { + data[i] = i; + } + data[count] = 0; + break; + case GL_UNSIGNED_BYTE: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_SHORT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + case GL_UNSIGNED_INT: + for (int i = 0; i < count; i++) + { + data[i] = static_cast(indices)[i]; + } + data[count] = static_cast(indices)[0]; + break; + default: UNREACHABLE(); + } + + if (!mLineLoopIB->unmapBuffer()) + { + ERR("Could not unmap index buffer for GL_LINE_LOOP."); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + if (mAppliedIBSerial != mLineLoopIB->getSerial()) + { + IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(mLineLoopIB->getIndexBuffer()); + + mDevice->SetIndices(indexBuffer->getBuffer()); + mAppliedIBSerial = mLineLoopIB->getSerial(); + } + + mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count); +} + +template +static void drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices, int minIndex) +{ + for (int i = 0; i < count; i++) + { + unsigned int indexValue = static_cast(static_cast(indices)[i]) - minIndex; + device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1); + } +} + +void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) +{ + // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call + // for each individual point. This call is not expected to happen often. + + if (elementArrayBuffer) + { + BufferImpl *storage = elementArrayBuffer->getImplementation(); + intptr_t offset = reinterpret_cast(indices); + indices = static_cast(storage->getData()) + offset; + } + + switch (type) + { + case GL_UNSIGNED_BYTE: drawPoints(mDevice, count, indices, minIndex); break; + case GL_UNSIGNED_SHORT: drawPoints(mDevice, count, indices, minIndex); break; + case GL_UNSIGNED_INT: drawPoints(mDevice, count, indices, minIndex); break; + default: UNREACHABLE(); + } +} + +void Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive) +{ + ASSERT(!transformFeedbackActive); + ASSERT(!rasterizerDiscard); + + ShaderExecutable *vertexExe = programBinary->getVertexExecutableForInputLayout(inputLayout); + ShaderExecutable *pixelExe = programBinary->getPixelExecutableForFramebuffer(framebuffer); + + IDirect3DVertexShader9 *vertexShader = (vertexExe ? ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader() : NULL); + IDirect3DPixelShader9 *pixelShader = (pixelExe ? ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader() : NULL); + + if (vertexShader != mAppliedVertexShader) + { + mDevice->SetVertexShader(vertexShader); + mAppliedVertexShader = vertexShader; + } + + if (pixelShader != mAppliedPixelShader) + { + mDevice->SetPixelShader(pixelShader); + mAppliedPixelShader = pixelShader; + } + + // D3D9 has a quirk where creating multiple shaders with the same content + // can return the same shader pointer. Because GL programs store different data + // per-program, checking the program serial guarantees we upload fresh + // uniform data even if our shader pointers are the same. + // https://code.google.com/p/angleproject/issues/detail?id=661 + unsigned int programSerial = programBinary->getSerial(); + if (programSerial != mAppliedProgramSerial) + { + programBinary->dirtyAllUniforms(); + mDxUniformsDirty = true; + mAppliedProgramSerial = programSerial; + } +} + +void Renderer9::applyUniforms(const gl::ProgramBinary &programBinary) +{ + const std::vector &uniformArray = programBinary.getUniforms(); + + for (size_t uniformIndex = 0; uniformIndex < uniformArray.size(); uniformIndex++) + { + gl::LinkedUniform *targetUniform = uniformArray[uniformIndex]; + + if (targetUniform->dirty) + { + GLfloat *f = (GLfloat*)targetUniform->data; + GLint *i = (GLint*)targetUniform->data; + + switch (targetUniform->type) + { + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + break; + case GL_BOOL: + case GL_BOOL_VEC2: + case GL_BOOL_VEC3: + case GL_BOOL_VEC4: + applyUniformnbv(targetUniform, i); + break; + case GL_FLOAT: + case GL_FLOAT_VEC2: + case GL_FLOAT_VEC3: + case GL_FLOAT_VEC4: + case GL_FLOAT_MAT2: + case GL_FLOAT_MAT3: + case GL_FLOAT_MAT4: + applyUniformnfv(targetUniform, f); + break; + case GL_INT: + case GL_INT_VEC2: + case GL_INT_VEC3: + case GL_INT_VEC4: + applyUniformniv(targetUniform, i); + break; + default: + UNREACHABLE(); + } + } + } + + // Driver uniforms + if (mDxUniformsDirty) + { + mDevice->SetVertexShaderConstantF(0, (float*)&mVertexConstants, sizeof(dx_VertexConstants) / sizeof(float[4])); + mDevice->SetPixelShaderConstantF(0, (float*)&mPixelConstants, sizeof(dx_PixelConstants) / sizeof(float[4])); + mDxUniformsDirty = false; + } +} + +void Renderer9::applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v) +{ + if (targetUniform->isReferencedByFragmentShader()) + { + mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount); + } + + if (targetUniform->isReferencedByVertexShader()) + { + mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount); + } +} + +void Renderer9::applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v) +{ + ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); + GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; + + for (unsigned int i = 0; i < targetUniform->registerCount; i++) + { + vector[i][0] = (GLfloat)v[4 * i + 0]; + vector[i][1] = (GLfloat)v[4 * i + 1]; + vector[i][2] = (GLfloat)v[4 * i + 2]; + vector[i][3] = (GLfloat)v[4 * i + 3]; + } + + applyUniformnfv(targetUniform, (GLfloat*)vector); +} + +void Renderer9::applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v) +{ + ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); + GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; + + for (unsigned int i = 0; i < targetUniform->registerCount; i++) + { + vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f; + vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f; + vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f; + vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f; + } + + applyUniformnfv(targetUniform, (GLfloat*)vector); +} + +void 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; + } + + bool clearColor = clearParams.clearColor[0]; + for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) + { + if (clearParams.clearColor[i] != clearColor) + { + // Clearing individual buffers other than buffer zero is not supported by Renderer9 and ES 2.0 + UNREACHABLE(); + return; + } + } + + float depth = gl::clamp01(clearParams.depthClearValue); + DWORD stencil = clearParams.stencilClearValue & 0x000000FF; + + unsigned int stencilUnmasked = 0x0; + if (clearParams.clearStencil && frameBuffer->hasStencil()) + { + unsigned int stencilSize = gl::GetStencilBits(frameBuffer->getStencilbuffer()->getActualFormat()); + stencilUnmasked = (0x1 << stencilSize) - 1; + } + + const bool needMaskedStencilClear = clearParams.clearStencil && + (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; + + bool needMaskedColorClear = false; + D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0); + if (clearColor) + { + 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); + + 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>((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)) + { + needMaskedColorClear = true; + } + } + + if (needMaskedColorClear || needMaskedStencilClear) + { + // State which is altered in all paths from this point to the clear call is saved. + // State which is altered in only some paths will be flagged dirty in the case that + // that path is taken. + HRESULT hr; + if (mMaskedClearSavedState == NULL) + { + hr = mDevice->BeginStateBlock(); + ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); + + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); + mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); + mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); + mDevice->SetPixelShader(NULL); + mDevice->SetVertexShader(NULL); + mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); + mDevice->SetStreamSource(0, NULL, 0, 0); + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); + mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); + mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); + + for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mDevice->SetStreamSourceFreq(i, 1); + } + + hr = mDevice->EndStateBlock(&mMaskedClearSavedState); + ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); + } + + ASSERT(mMaskedClearSavedState != NULL); + + if (mMaskedClearSavedState != NULL) + { + hr = mMaskedClearSavedState->Capture(); + ASSERT(SUCCEEDED(hr)); + } + + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); + mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); + mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + + if (clearColor) + { + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, + gl_d3d9::ConvertColorMask(clearParams.colorMaskRed, + clearParams.colorMaskGreen, + clearParams.colorMaskBlue, + clearParams.colorMaskAlpha)); + } + else + { + mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); + } + + if (stencilUnmasked != 0x0 && clearParams.clearStencil) + { + mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); + mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE); + mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); + mDevice->SetRenderState(D3DRS_STENCILREF, stencil); + mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask); + mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE); + mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE); + mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); + } + else + { + mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); + } + + mDevice->SetPixelShader(NULL); + mDevice->SetVertexShader(NULL); + mDevice->SetFVF(D3DFVF_XYZRHW); + mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); + mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); + mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); + mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); + + for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mDevice->SetStreamSourceFreq(i, 1); + } + + float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges + quad[0][0] = -0.5f; + quad[0][1] = mRenderTargetDesc.height - 0.5f; + quad[0][2] = 0.0f; + quad[0][3] = 1.0f; + + quad[1][0] = mRenderTargetDesc.width - 0.5f; + quad[1][1] = mRenderTargetDesc.height - 0.5f; + quad[1][2] = 0.0f; + quad[1][3] = 1.0f; + + quad[2][0] = -0.5f; + quad[2][1] = -0.5f; + quad[2][2] = 0.0f; + quad[2][3] = 1.0f; + + quad[3][0] = mRenderTargetDesc.width - 0.5f; + quad[3][1] = -0.5f; + quad[3][2] = 0.0f; + quad[3][3] = 1.0f; + + startScene(); + mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4])); + + if (clearParams.clearDepth) + { + mDevice->SetRenderState(D3DRS_ZENABLE, TRUE); + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); + mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil); + } + + if (mMaskedClearSavedState != NULL) + { + mMaskedClearSavedState->Apply(); + } + } + else if (clearColor || clearParams.clearDepth || clearParams.clearStencil) + { + DWORD dxClearFlags = 0; + if (clearColor) + { + dxClearFlags |= D3DCLEAR_TARGET; + } + if (clearParams.clearDepth) + { + dxClearFlags |= D3DCLEAR_ZBUFFER; + } + if (clearParams.clearStencil) + { + dxClearFlags |= D3DCLEAR_STENCIL; + } + + mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil); + } +} + +void Renderer9::markAllStateDirty() +{ + mAppliedRenderTargetSerial = 0; + mAppliedDepthbufferSerial = 0; + mAppliedStencilbufferSerial = 0; + mDepthStencilInitialized = false; + mRenderTargetDescInitialized = false; + + mForceSetDepthStencilState = true; + mForceSetRasterState = true; + mForceSetScissor = true; + mForceSetViewport = true; + mForceSetBlendState = true; + + for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) + { + mForceSetVertexSamplerStates[i] = true; + mCurVertexTextureSerials[i] = 0; + } + for (unsigned int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++) + { + mForceSetPixelSamplerStates[i] = true; + mCurPixelTextureSerials[i] = 0; + } + + mAppliedIBSerial = 0; + mAppliedVertexShader = NULL; + mAppliedPixelShader = NULL; + mAppliedProgramSerial = 0; + mDxUniformsDirty = true; + + mVertexDeclarationCache.markStateDirty(); +} + +void Renderer9::releaseDeviceResources() +{ + for (size_t i = 0; i < mEventQueryPool.size(); i++) + { + SafeRelease(mEventQueryPool[i]); + } + mEventQueryPool.clear(); + + SafeRelease(mMaskedClearSavedState); + + mVertexShaderCache.clear(); + mPixelShaderCache.clear(); + + SafeDelete(mBlit); + SafeDelete(mVertexDataManager); + SafeDelete(mIndexDataManager); + SafeDelete(mLineLoopIB); + + for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) + { + SafeDelete(mNullColorbufferCache[i].buffer); + } +} + +void Renderer9::notifyDeviceLost() +{ + mDeviceLost = true; + mDisplay->notifyDeviceLost(); +} + +bool Renderer9::isDeviceLost() +{ + return mDeviceLost; +} + +// set notify to true to broadcast a message to all contexts of the device loss +bool Renderer9::testDeviceLost(bool notify) +{ + HRESULT status = getDeviceStatusCode(); + bool isLost = FAILED(status); + + if (isLost) + { + // ensure we note the device loss -- + // we'll probably get this done again by notifyDeviceLost + // but best to remember it! + // Note that we don't want to clear the device loss status here + // -- this needs to be done by resetDevice + mDeviceLost = true; + if (notify) + { + notifyDeviceLost(); + } + } + + return isLost; +} + +HRESULT Renderer9::getDeviceStatusCode() +{ + HRESULT status = D3D_OK; + + if (mDeviceEx) + { + status = mDeviceEx->CheckDeviceState(NULL); + } + else if (mDevice) + { + status = mDevice->TestCooperativeLevel(); + } + + return status; +} + +bool Renderer9::testDeviceResettable() +{ + // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted + // DEVICEREMOVED indicates the device has been stopped and must be recreated + switch (getDeviceStatusCode()) + { + case D3DERR_DEVICENOTRESET: + case D3DERR_DEVICEHUNG: + return true; + case D3DERR_DEVICELOST: + return (mDeviceEx != NULL); + case D3DERR_DEVICEREMOVED: + ASSERT(mDeviceEx != NULL); + return isRemovedDeviceResettable(); + default: + return false; + } +} + +bool Renderer9::resetDevice() +{ + releaseDeviceResources(); + + D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); + + HRESULT result = D3D_OK; + bool lost = testDeviceLost(false); + bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED); + + // Device Removed is a feature which is only present with D3D9Ex + ASSERT(mDeviceEx != NULL || !removedDevice); + + for (int attempts = 3; lost && attempts > 0; attempts--) + { + if (removedDevice) + { + // Device removed, which may trigger on driver reinstallation, + // may cause a longer wait other reset attempts before the + // system is ready to handle creating a new device. + Sleep(800); + lost = !resetRemovedDevice(); + } + else if (mDeviceEx) + { + Sleep(500); // Give the graphics driver some CPU time + result = mDeviceEx->ResetEx(&presentParameters, NULL); + lost = testDeviceLost(false); + } + else + { + result = mDevice->TestCooperativeLevel(); + while (result == D3DERR_DEVICELOST) + { + Sleep(100); // Give the graphics driver some CPU time + result = mDevice->TestCooperativeLevel(); + } + + if (result == D3DERR_DEVICENOTRESET) + { + result = mDevice->Reset(&presentParameters); + } + lost = testDeviceLost(false); + } + } + + if (FAILED(result)) + { + ERR("Reset/ResetEx failed multiple times: 0x%08X", result); + return false; + } + + if (removedDevice && lost) + { + ERR("Device lost reset failed multiple times"); + return false; + } + + // If the device was removed, we already finished re-initialization in resetRemovedDevice + if (!removedDevice) + { + // reset device defaults + initializeDevice(); + } + + mDeviceLost = false; + + return true; +} + +bool Renderer9::isRemovedDeviceResettable() const +{ + bool success = false; + +#ifdef ANGLE_ENABLE_D3D9EX + IDirect3D9Ex *d3d9Ex = NULL; + typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); + Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); + + if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex))) + { + D3DCAPS9 deviceCaps; + HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps); + success = SUCCEEDED(result); + } + + SafeRelease(d3d9Ex); +#else + ASSERT(UNREACHABLE()); +#endif + + return success; +} + +bool Renderer9::resetRemovedDevice() +{ + // From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx: + // The hardware adapter has been removed. Application must destroy the device, do enumeration of + // adapters and create another Direct3D device. If application continues rendering without + // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only. + release(); + return (initialize() == EGL_SUCCESS); +} + +DWORD Renderer9::getAdapterVendor() const +{ + return mAdapterIdentifier.VendorId; +} + +std::string Renderer9::getRendererDescription() const +{ + std::ostringstream rendererString; + + rendererString << mAdapterIdentifier.Description; + if (getShareHandleSupport()) + { + rendererString << " Direct3D9Ex"; + } + else + { + rendererString << " Direct3D9"; + } + + rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion); + rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion); + + return rendererString.str(); +} + +GUID Renderer9::getAdapterIdentifier() const +{ + return mAdapterIdentifier.DeviceIdentifier; +} + +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. +} + +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; +} + +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. + return (mD3d9Ex != NULL) && !gl::perfActive(); +} + +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); +} + +DWORD Renderer9::getCapsDeclTypes() const +{ + return mDeviceCaps.DeclTypes; +} + +int Renderer9::getMinSwapInterval() const +{ + return mMinSwapInterval; +} + +int Renderer9::getMaxSwapInterval() const +{ + return mMaxSwapInterval; +} + +int Renderer9::getMaxSupportedSamples() const +{ + return mMaxSupportedSamples; +} + +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 result = false; + + if (source && dest) + { + TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source->getStorageInstance()); + TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest->getStorageInstance()); + + int levels = source9->getLevelCount(); + for (int i = 0; i < levels; ++i) + { + IDirect3DSurface9 *srcSurf = source9->getSurfaceLevel(i, false); + IDirect3DSurface9 *dstSurf = dest9->getSurfaceLevel(i, false); + + result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); + + SafeRelease(srcSurf); + SafeRelease(dstSurf); + + if (!result) + { + return false; + } + } + } + + return result; +} + +bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) +{ + bool result = false; + + if (source && dest) + { + TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source->getStorageInstance()); + TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest->getStorageInstance()); + int levels = source9->getLevelCount(); + for (int f = 0; f < 6; f++) + { + for (int i = 0; i < levels; i++) + { + IDirect3DSurface9 *srcSurf = source9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false); + IDirect3DSurface9 *dstSurf = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true); + + result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); + + SafeRelease(srcSurf); + SafeRelease(dstSurf); + + if (!result) + { + return false; + } + } + } + } + + return result; +} + +bool Renderer9::copyToRenderTarget(TextureStorageInterface3D *dest, TextureStorageInterface3D *source) +{ + // 3D textures are not available in the D3D9 backend. + UNREACHABLE(); + return false; +} + +bool Renderer9::copyToRenderTarget(TextureStorageInterface2DArray *dest, TextureStorageInterface2DArray *source) +{ + // 2D array textures are not supported by the D3D9 backend. + UNREACHABLE(); + return false; +} + +D3DPOOL Renderer9::getBufferPool(DWORD usage) const +{ + if (mD3d9Ex != NULL) + { + return D3DPOOL_DEFAULT; + } + else + { + if (!(usage & D3DUSAGE_DYNAMIC)) + { + return D3DPOOL_MANAGED; + } + } + + return D3DPOOL_DEFAULT; +} + +bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) +{ + RECT rect; + rect.left = sourceRect.x; + rect.top = sourceRect.y; + rect.right = sourceRect.x + sourceRect.width; + rect.bottom = sourceRect.y + sourceRect.height; + + return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, level); +} + +bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) +{ + RECT rect; + rect.left = sourceRect.x; + rect.top = sourceRect.y; + rect.right = sourceRect.x + sourceRect.width; + rect.bottom = sourceRect.y + sourceRect.height; + + return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level); +} + +bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, + GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface3D *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) +{ + // 2D array textures are not available in the D3D9 backend. + UNREACHABLE(); + return false; +} + +bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect, + const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) +{ + ASSERT(filter == GL_NEAREST); + + endScene(); + + if (blitRenderTarget) + { + gl::FramebufferAttachment *readBuffer = readFramebuffer->getColorbuffer(0); + gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getColorbuffer(0); + RenderTarget9 *readRenderTarget = NULL; + RenderTarget9 *drawRenderTarget = NULL; + IDirect3DSurface9* readSurface = NULL; + IDirect3DSurface9* drawSurface = NULL; + + if (readBuffer) + { + readRenderTarget = RenderTarget9::makeRenderTarget9(readBuffer->getRenderTarget()); + } + if (drawBuffer) + { + drawRenderTarget = RenderTarget9::makeRenderTarget9(drawBuffer->getRenderTarget()); + } + + if (readRenderTarget) + { + readSurface = readRenderTarget->getSurface(); + } + if (drawRenderTarget) + { + drawSurface = drawRenderTarget->getSurface(); + } + + if (!readSurface || !drawSurface) + { + ERR("Failed to retrieve the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1); + gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1); + + RECT srcRect; + srcRect.left = readRect.x; + srcRect.right = readRect.x + readRect.width; + srcRect.top = readRect.y; + srcRect.bottom = readRect.y + readRect.height; + + RECT dstRect; + dstRect.left = drawRect.x; + dstRect.right = drawRect.x + drawRect.width; + dstRect.top = drawRect.y; + dstRect.bottom = drawRect.y + drawRect.height; + + // Clip the rectangles to the scissor rectangle + if (scissor) + { + if (dstRect.left < scissor->x) + { + srcRect.left += (scissor->x - dstRect.left); + dstRect.left = scissor->x; + } + if (dstRect.top < scissor->y) + { + srcRect.top += (scissor->y - dstRect.top); + dstRect.top = scissor->y; + } + if (dstRect.right > scissor->x + scissor->width) + { + srcRect.right -= (dstRect.right - (scissor->x + scissor->width)); + dstRect.right = scissor->x + scissor->width; + } + if (dstRect.bottom > scissor->y + scissor->height) + { + srcRect.bottom -= (dstRect.bottom - (scissor->y + scissor->height)); + dstRect.bottom = scissor->y + scissor->height; + } + } + + // Clip the rectangles to the destination size + if (dstRect.left < 0) + { + srcRect.left += -dstRect.left; + dstRect.left = 0; + } + if (dstRect.right > dstSize.width) + { + srcRect.right -= (dstRect.right - dstSize.width); + dstRect.right = dstSize.width; + } + if (dstRect.top < 0) + { + srcRect.top += -dstRect.top; + dstRect.top = 0; + } + if (dstRect.bottom > dstSize.height) + { + srcRect.bottom -= (dstRect.bottom - dstSize.height); + dstRect.bottom = dstSize.height; + } + + // Clip the rectangles to the source size + if (srcRect.left < 0) + { + dstRect.left += -srcRect.left; + srcRect.left = 0; + } + if (srcRect.right > srcSize.width) + { + dstRect.right -= (srcRect.right - srcSize.width); + srcRect.right = srcSize.width; + } + if (srcRect.top < 0) + { + dstRect.top += -srcRect.top; + srcRect.top = 0; + } + if (srcRect.bottom > srcSize.height) + { + dstRect.bottom -= (srcRect.bottom - srcSize.height); + srcRect.bottom = srcSize.height; + } + + HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE); + + SafeRelease(readSurface); + SafeRelease(drawSurface); + + if (FAILED(result)) + { + ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); + return false; + } + } + + if (blitDepth || blitStencil) + { + gl::FramebufferAttachment *readBuffer = readFramebuffer->getDepthOrStencilbuffer(); + gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer(); + RenderTarget9 *readDepthStencil = NULL; + RenderTarget9 *drawDepthStencil = NULL; + IDirect3DSurface9* readSurface = NULL; + IDirect3DSurface9* drawSurface = NULL; + + if (readBuffer) + { + readDepthStencil = RenderTarget9::makeRenderTarget9(readBuffer->getDepthStencil()); + } + if (drawBuffer) + { + drawDepthStencil = RenderTarget9::makeRenderTarget9(drawBuffer->getDepthStencil()); + } + + if (readDepthStencil) + { + readSurface = readDepthStencil->getSurface(); + } + if (drawDepthStencil) + { + drawSurface = drawDepthStencil->getSurface(); + } + + if (!readSurface || !drawSurface) + { + ERR("Failed to retrieve the render target."); + return gl::error(GL_OUT_OF_MEMORY, false); + } + + HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE); + + SafeRelease(readSurface); + SafeRelease(drawSurface); + + if (FAILED(result)) + { + ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); + return false; + } + } + + return true; +} + +void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, + GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, void* pixels) +{ + ASSERT(pack.pixelBuffer.get() == NULL); + + RenderTarget9 *renderTarget = NULL; + IDirect3DSurface9 *surface = NULL; + gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0); + + if (colorbuffer) + { + renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); + } + + if (renderTarget) + { + surface = renderTarget->getSurface(); + } + + if (!surface) + { + // context must be lost + return; + } + + D3DSURFACE_DESC desc; + surface->GetDesc(&desc); + + if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) + { + UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target + SafeRelease(surface); + return gl::error(GL_OUT_OF_MEMORY); + } + + HRESULT result; + IDirect3DSurface9 *systemSurface = NULL; + bool directToPixels = !pack.reverseRowOrder && pack.alignment <= 4 && getShareHandleSupport() && + x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height && + desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE; + if (directToPixels) + { + // Use the pixels ptr as a shared handle to write directly into client's memory + result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, + D3DPOOL_SYSTEMMEM, &systemSurface, &pixels); + if (FAILED(result)) + { + // Try again without the shared handle + directToPixels = false; + } + } + + if (!directToPixels) + { + result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, + D3DPOOL_SYSTEMMEM, &systemSurface, NULL); + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + SafeRelease(surface); + return gl::error(GL_OUT_OF_MEMORY); + } + } + + result = mDevice->GetRenderTargetData(surface, systemSurface); + SafeRelease(surface); + + if (FAILED(result)) + { + SafeRelease(systemSurface); + + // It turns out that D3D will sometimes produce more error + // codes than those documented. + if (d3d9::isDeviceLostError(result)) + { + notifyDeviceLost(); + return gl::error(GL_OUT_OF_MEMORY); + } + else + { + UNREACHABLE(); + return; + } + + } + + if (directToPixels) + { + SafeRelease(systemSurface); + return; + } + + RECT rect; + rect.left = gl::clamp(x, 0L, static_cast(desc.Width)); + rect.top = gl::clamp(y, 0L, static_cast(desc.Height)); + rect.right = gl::clamp(x + width, 0L, static_cast(desc.Width)); + rect.bottom = gl::clamp(y + height, 0L, static_cast(desc.Height)); + + D3DLOCKED_RECT lock; + result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY); + + if (FAILED(result)) + { + UNREACHABLE(); + SafeRelease(systemSurface); + + return; // No sensible error to generate + } + + unsigned char *source; + int inputPitch; + if (pack.reverseRowOrder) + { + source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); + inputPitch = -lock.Pitch; + } + else + { + source = (unsigned char*)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) + { + // 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); + } + } + else + { + GLenum destInternalFormat = gl::GetSizedInternalFormat(format, type); + GLuint destPixelSize = gl::GetPixelBytes(destInternalFormat); + GLuint sourcePixelSize = gl::GetPixelBytes(sourceInternalFormat); + + ColorCopyFunction fastCopyFunc = d3d9::GetFastCopyFunction(desc.Format, format, type); + if (fastCopyFunc) + { + // Fast copy is possible through some special function + for (int y = 0; y < rect.bottom - rect.top; y++) + { + for (int x = 0; x < rect.right - rect.left; x++) + { + void *dest = static_cast(pixels) + y * outputPitch + x * destPixelSize; + void *src = static_cast(source) + y * inputPitch + x * sourcePixelSize; + + fastCopyFunc(src, dest); + } + } + } + else + { + ColorReadFunction readFunc = d3d9::GetColorReadFunction(desc.Format); + ColorWriteFunction writeFunc = gl::GetColorWriteFunction(format, type); + + gl::ColorF temp; + + 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; + + // readFunc and writeFunc will be using the same type of color, CopyTexImage + // will not allow the copy otherwise. + readFunc(src, &temp); + writeFunc(&temp, dest); + } + } + } + } + + systemSurface->UnlockRect(); + SafeRelease(systemSurface); +} + +RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth) +{ + SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); + IDirect3DSurface9 *surface = NULL; + if (depth) + { + surface = swapChain9->getDepthStencil(); + } + else + { + surface = swapChain9->getRenderTarget(); + } + + RenderTarget9 *renderTarget = new RenderTarget9(this, surface); + + return renderTarget; +} + +RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples) +{ + RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples); + return renderTarget; +} + +ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers) +{ + // Transform feedback is not supported in ES2 or D3D9 + ASSERT(transformFeedbackVaryings.size() == 0); + + ShaderExecutable9 *executable = NULL; + + switch (type) + { + case rx::SHADER_VERTEX: + { + IDirect3DVertexShader9 *vshader = createVertexShader((DWORD*)function, length); + if (vshader) + { + executable = new ShaderExecutable9(function, length, vshader); + } + } + break; + case rx::SHADER_PIXEL: + { + IDirect3DPixelShader9 *pshader = createPixelShader((DWORD*)function, length); + if (pshader) + { + executable = new ShaderExecutable9(function, length, pshader); + } + } + break; + default: + UNREACHABLE(); + break; + } + + return executable; +} + +ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, D3DWorkaroundType workaround) +{ + // Transform feedback is not supported in ES2 or D3D9 + ASSERT(transformFeedbackVaryings.size() == 0); + + const char *profile = NULL; + + switch (type) + { + case rx::SHADER_VERTEX: + profile = getMajorShaderModel() >= 3 ? "vs_3_0" : "vs_2_0"; + break; + case rx::SHADER_PIXEL: + profile = getMajorShaderModel() >= 3 ? "ps_3_0" : "ps_2_0"; + break; + default: + UNREACHABLE(); + return NULL; + } + + UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL; + + if (workaround == ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION) + { + flags = D3DCOMPILE_SKIP_OPTIMIZATION; + } + else if (workaround == ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION) + { + flags = D3DCOMPILE_OPTIMIZATION_LEVEL3; + } + else ASSERT(workaround == ANGLE_D3D_WORKAROUND_NONE); + + if (gl::perfActive()) + { +#ifndef NDEBUG + flags = D3DCOMPILE_SKIP_OPTIMIZATION; +#endif + + flags |= D3DCOMPILE_DEBUG; + + std::string sourcePath = getTempPath(); + std::string sourceText = std::string("#line 2 \"") + sourcePath + std::string("\"\n\n") + std::string(shaderHLSL); + writeFile(sourcePath.c_str(), sourceText.c_str(), sourceText.size()); + } + + // Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options. + // Try the default flags first and if compilation fails, try some alternatives. + const UINT extraFlags[] = + { + flags, + flags | D3DCOMPILE_AVOID_FLOW_CONTROL, + flags | D3DCOMPILE_PREFER_FLOW_CONTROL + }; + + const static char *extraFlagNames[] = + { + "default", + "avoid flow control", + "prefer flow control" + }; + + int attempts = ArraySize(extraFlags); + + ID3DBlob *binary = (ID3DBlob*)mCompiler.compileToBinary(infoLog, shaderHLSL, profile, extraFlags, extraFlagNames, attempts); + if (!binary) + { + return NULL; + } + + ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type, + transformFeedbackVaryings, separatedOutputBuffers); + SafeRelease(binary); + + return executable; +} + +rx::UniformStorage *Renderer9::createUniformStorage(size_t storageSize) +{ + return new UniformStorage(storageSize); +} + +bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) +{ + return mBlit->boxFilter(source, dest); +} + +D3DPOOL Renderer9::getTexturePool(DWORD usage) const +{ + if (mD3d9Ex != NULL) + { + return D3DPOOL_DEFAULT; + } + else + { + if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET))) + { + return D3DPOOL_MANAGED; + } + } + + return D3DPOOL_DEFAULT; +} + +bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged) +{ + if (source && dest) + { + HRESULT result = D3DERR_OUTOFVIDEOMEMORY; + + if (fromManaged) + { + D3DSURFACE_DESC desc; + source->GetDesc(&desc); + + IDirect3DSurface9 *surf = 0; + result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); + + if (SUCCEEDED(result)) + { + Image9::copyLockableSurfaces(surf, source); + result = mDevice->UpdateSurface(surf, NULL, dest, NULL); + SafeRelease(surf); + } + } + else + { + endScene(); + result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE); + } + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + return false; + } + } + + return true; +} + +Image *Renderer9::createImage() +{ + return new Image9(); +} + +void Renderer9::generateMipmap(Image *dest, Image *src) +{ + Image9 *src9 = Image9::makeImage9(src); + Image9 *dst9 = Image9::makeImage9(dest); + Image9::generateMipmap(dst9, src9); +} + +TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain) +{ + SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); + return new TextureStorage9_2D(this, swapChain9); +} + +TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) +{ + return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels); +} + +TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) +{ + return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels); +} + +TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +{ + // 3D textures are not supported by the D3D9 backend. + UNREACHABLE(); + + return NULL; +} + +TextureStorage *Renderer9::createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) +{ + // 2D array textures are not supported by the D3D9 backend. + UNREACHABLE(); + + return NULL; +} + +Texture2DImpl *Renderer9::createTexture2D() +{ + return new TextureD3D_2D(this); +} + +TextureCubeImpl *Renderer9::createTextureCube() +{ + return new TextureD3D_Cube(this); +} + +Texture3DImpl *Renderer9::createTexture3D() +{ + return new TextureD3D_3D(this); +} + +Texture2DArrayImpl *Renderer9::createTexture2DArray() +{ + return new TextureD3D_2DArray(this); +} + +bool Renderer9::getLUID(LUID *adapterLuid) const +{ + adapterLuid->HighPart = 0; + adapterLuid->LowPart = 0; + + if (mD3d9Ex) + { + mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid); + return true; + } + + 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); +} + +GLenum Renderer9::getVertexComponentType(const gl::VertexFormat &vertexFormat) const +{ + D3DDECLTYPE declType = d3d9::GetNativeVertexFormat(vertexFormat); + return d3d9::GetDeclTypeComponentType(declType); +} + +void Renderer9::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const +{ + d3d9_gl::GenerateCaps(mD3d9, mDevice, mDeviceType, mAdapter, outCaps, outTextureCaps, outExtensions); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h new file mode 100644 index 0000000000..070623c9db --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h @@ -0,0 +1,364 @@ +// +// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// Renderer9.h: Defines a back-end specific class for the D3D9 renderer. + +#ifndef LIBGLESV2_RENDERER_RENDERER9_H_ +#define LIBGLESV2_RENDERER_RENDERER9_H_ + +#include "common/angleutils.h" +#include "common/mathutil.h" +#include "libGLESv2/renderer/d3d/HLSLCompiler.h" +#include "libGLESv2/renderer/d3d/d3d9/ShaderCache.h" +#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h" +#include "libGLESv2/renderer/Renderer.h" +#include "libGLESv2/renderer/RenderTarget.h" + +namespace gl +{ +class FramebufferAttachment; +} + +namespace rx +{ +class VertexDataManager; +class IndexDataManager; +class StreamingIndexBufferInterface; +struct TranslatedAttribute; +class Blit9; + +class Renderer9 : public Renderer +{ + public: + Renderer9(egl::Display *display, EGLNativeDisplayType hDc, EGLint requestedDisplay); + virtual ~Renderer9(); + + static Renderer9 *makeRenderer9(Renderer *renderer); + + virtual EGLint initialize(); + virtual bool resetDevice(); + + virtual int generateConfigs(ConfigDesc **configDescList); + virtual void deleteConfigs(ConfigDesc *configDescList); + + void startScene(); + void endScene(); + + virtual void sync(bool block); + + virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); + + IDirect3DQuery9* allocateEventQuery(); + void freeEventQuery(IDirect3DQuery9* query); + + // resource creation + IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length); + IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length); + HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer); + HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer); + 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 bool 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 void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); + virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, + bool ignoreViewport); + + virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); + virtual void applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer, + bool rasterizerDiscard, bool transformFeedbackActive); + virtual void 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 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 void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); + + virtual void markAllStateDirty(); + + // lost device + void notifyDeviceLost(); + virtual bool isDeviceLost(); + virtual bool testDeviceLost(bool notify); + virtual bool testDeviceResettable(); + + IDirect3DDevice9 *getDevice() { return mDevice; } + virtual DWORD getAdapterVendor() const; + 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 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); + + // RenderTarget creation + virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); + virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples); + + // Shader operations + virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers); + virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, + const std::vector &transformFeedbackVaryings, + bool separatedOutputBuffers, D3DWorkaroundType workaround); + virtual UniformStorage *createUniformStorage(size_t storageSize); + + // Image operations + virtual Image *createImage(); + virtual void generateMipmap(Image *dest, Image *source); + virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); + virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); + virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels); + virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); + virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels); + + // Texture creation + virtual Texture2DImpl *createTexture2D(); + virtual TextureCubeImpl *createTextureCube(); + virtual Texture3DImpl *createTexture3D(); + virtual Texture2DArrayImpl *createTexture2DArray(); + + // Buffer creation + virtual BufferImpl *createBuffer(); + virtual VertexBuffer *createVertexBuffer(); + virtual IndexBuffer *createIndexBuffer(); + + // Vertex Array creation + virtual VertexArrayImpl *createVertexArray(); + + // Query and Fence creation + virtual QueryImpl *createQuery(GLenum type); + virtual FenceImpl *createFence(); + + // 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, + GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea); + + // D3D9-renderer specific methods + bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); + + 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; + + private: + DISALLOW_COPY_AND_ASSIGN(Renderer9); + + virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const; + + void release(); + + void applyUniformnfv(gl::LinkedUniform *targetUniform, const GLfloat *v); + void applyUniformniv(gl::LinkedUniform *targetUniform, const GLint *v); + void applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v); + + 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); + + bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); + gl::FramebufferAttachment *getNullColorbuffer(gl::FramebufferAttachment *depthbuffer); + + D3DPOOL getBufferPool(DWORD usage) const; + + HMODULE mD3d9Module; + HDC mDc; + + void initializeDevice(); + D3DPRESENT_PARAMETERS getDefaultPresentParameters(); + void releaseDeviceResources(); + + HRESULT getDeviceStatusCode(); + bool isRemovedDeviceResettable() const; + bool resetRemovedDevice(); + + UINT mAdapter; + D3DDEVTYPE mDeviceType; + IDirect3D9 *mD3d9; // Always valid after successful initialization. + IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported. + IDirect3DDevice9 *mDevice; + IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported. + + HLSLCompiler mCompiler; + + Blit9 *mBlit; + + HWND mDeviceWindow; + + bool mDeviceLost; + D3DCAPS9 mDeviceCaps; + D3DADAPTER_IDENTIFIER9 mAdapterIdentifier; + + D3DPRIMITIVETYPE mPrimitiveType; + int mPrimitiveCount; + GLsizei mRepeatDraw; + + bool mSceneStarted; + int mMinSwapInterval; + int mMaxSwapInterval; + + bool mVertexTextureSupport; + + 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; + unsigned int mAppliedStencilbufferSerial; + bool mDepthStencilInitialized; + bool mRenderTargetDescInitialized; + rx::RenderTarget::Desc mRenderTargetDesc; + unsigned int mCurStencilSize; + unsigned int mCurDepthSize; + + IDirect3DStateBlock9 *mMaskedClearSavedState; + + // previously set render states + bool mForceSetDepthStencilState; + gl::DepthStencilState mCurDepthStencilState; + int mCurStencilRef; + int mCurStencilBackRef; + bool mCurFrontFaceCCW; + + bool mForceSetRasterState; + gl::RasterizerState mCurRasterState; + + bool mForceSetScissor; + gl::Rectangle mCurScissor; + bool mScissorEnabled; + + bool mForceSetViewport; + gl::Rectangle mCurViewport; + float mCurNear; + float mCurFar; + float mCurDepthFront; + + bool mForceSetBlendState; + gl::BlendState mCurBlendState; + gl::ColorF mCurBlendColor; + GLuint mCurSampleMask; + + // Currently applied sampler states + bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + + bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; + gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; + + // Currently applied textures + unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; + unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS]; + + unsigned int mAppliedIBSerial; + IDirect3DVertexShader9 *mAppliedVertexShader; + IDirect3DPixelShader9 *mAppliedPixelShader; + unsigned int mAppliedProgramSerial; + + rx::dx_VertexConstants mVertexConstants; + rx::dx_PixelConstants mPixelConstants; + bool mDxUniformsDirty; + + // A pool of event queries that are currently unused. + std::vector mEventQueryPool; + VertexShaderCache mVertexShaderCache; + PixelShaderCache mPixelShaderCache; + + VertexDataManager *mVertexDataManager; + VertexDeclarationCache mVertexDeclarationCache; + + IndexDataManager *mIndexDataManager; + StreamingIndexBufferInterface *mLineLoopIB; + + enum { NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12 }; + struct NullColorbufferCacheEntry + { + UINT lruCount; + int width; + int height; + gl::FramebufferAttachment *buffer; + } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES]; + UINT mMaxNullColorbufferLRU; + +}; + +} +#endif // LIBGLESV2_RENDERER_RENDERER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h new file mode 100644 index 0000000000..a03528c9b5 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h @@ -0,0 +1,102 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderCache: Defines rx::ShaderCache, a cache of Direct3D shader objects +// keyed by their byte code. + +#ifndef LIBGLESV2_RENDERER_SHADER_CACHE_H_ +#define LIBGLESV2_RENDERER_SHADER_CACHE_H_ + +#include "common/debug.h" + +namespace rx +{ +template +class ShaderCache +{ + public: + ShaderCache() : mDevice(NULL) + { + } + + ~ShaderCache() + { + // Call clear while the device is still valid. + ASSERT(mMap.empty()); + } + + void initialize(IDirect3DDevice9* device) + { + mDevice = device; + } + + ShaderObject *create(const DWORD *function, size_t length) + { + std::string key(reinterpret_cast(function), length); + typename Map::iterator it = mMap.find(key); + if (it != mMap.end()) + { + it->second->AddRef(); + return it->second; + } + + ShaderObject *shader; + HRESULT result = createShader(function, &shader); + if (FAILED(result)) + { + return NULL; + } + + // Random eviction policy. + if (mMap.size() >= kMaxMapSize) + { + SafeRelease(mMap.begin()->second); + mMap.erase(mMap.begin()); + } + + shader->AddRef(); + mMap[key] = shader; + + return shader; + } + + void clear() + { + for (typename Map::iterator it = mMap.begin(); it != mMap.end(); ++it) + { + SafeRelease(it->second); + } + + mMap.clear(); + } + + private: + DISALLOW_COPY_AND_ASSIGN(ShaderCache); + + const static size_t kMaxMapSize = 100; + + HRESULT createShader(const DWORD *function, IDirect3DVertexShader9 **shader) + { + return mDevice->CreateVertexShader(function, shader); + } + + HRESULT createShader(const DWORD *function, IDirect3DPixelShader9 **shader) + { + return mDevice->CreatePixelShader(function, shader); + } + + typedef std::unordered_map Map; + Map mMap; + + IDirect3DDevice9 *mDevice; +}; + +typedef ShaderCache VertexShaderCache; +typedef ShaderCache PixelShaderCache; + +} + +#endif // LIBGLESV2_RENDERER_SHADER_CACHE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp new file mode 100644 index 0000000000..c10ddbf6ce --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp @@ -0,0 +1,54 @@ +#include "precompiled.h" +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader +// executable implementation details. + +#include "libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h" + +#include "common/debug.h" + +namespace rx +{ + +ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable) + : ShaderExecutable(function, length) +{ + mPixelExecutable = executable; + mVertexExecutable = NULL; +} + +ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable) + : ShaderExecutable(function, length) +{ + mVertexExecutable = executable; + mPixelExecutable = NULL; +} + +ShaderExecutable9::~ShaderExecutable9() +{ + SafeRelease(mVertexExecutable); + SafeRelease(mPixelExecutable); +} + +ShaderExecutable9 *ShaderExecutable9::makeShaderExecutable9(ShaderExecutable *executable) +{ + ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable9*, executable)); + return static_cast(executable); +} + +IDirect3DVertexShader9 *ShaderExecutable9::getVertexShader() const +{ + return mVertexExecutable; +} + +IDirect3DPixelShader9 *ShaderExecutable9::getPixelShader() const +{ + return mPixelExecutable; +} + +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h new file mode 100644 index 0000000000..fa1e6c2844 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h @@ -0,0 +1,39 @@ +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// ShaderExecutable9.h: Defines a D3D9-specific class to contain shader +// executable implementation details. + +#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ +#define LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ + +#include "libGLESv2/renderer/ShaderExecutable.h" + +namespace rx +{ + +class ShaderExecutable9 : public ShaderExecutable +{ + public: + ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable); + ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable); + virtual ~ShaderExecutable9(); + + static ShaderExecutable9 *makeShaderExecutable9(ShaderExecutable *executable); + + IDirect3DPixelShader9 *getPixelShader() const; + IDirect3DVertexShader9 *getVertexShader() const; + + private: + DISALLOW_COPY_AND_ASSIGN(ShaderExecutable9); + + IDirect3DPixelShader9 *mPixelExecutable; + IDirect3DVertexShader9 *mVertexExecutable; +}; + +} + +#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp new file mode 100644 index 0000000000..c6567b635f --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp @@ -0,0 +1,416 @@ +#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 +// found in the LICENSE file. +// + +// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain. + +#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h" +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ + +SwapChain9::SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle, + GLenum backBufferFormat, GLenum depthBufferFormat) + : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) +{ + mSwapChain = NULL; + mBackBuffer = NULL; + mDepthStencil = NULL; + mRenderTarget = NULL; + mOffscreenTexture = NULL; + mWidth = -1; + mHeight = -1; + mSwapInterval = -1; +} + +SwapChain9::~SwapChain9() +{ + release(); +} + +void SwapChain9::release() +{ + SafeRelease(mSwapChain); + SafeRelease(mBackBuffer); + SafeRelease(mDepthStencil); + SafeRelease(mRenderTarget); + SafeRelease(mOffscreenTexture); + + if (mWindow) + { + mShareHandle = NULL; + } +} + +static DWORD convertInterval(EGLint interval) +{ +#if ANGLE_FORCE_VSYNC_OFF + return D3DPRESENT_INTERVAL_IMMEDIATE; +#else + switch(interval) + { + case 0: return D3DPRESENT_INTERVAL_IMMEDIATE; + case 1: return D3DPRESENT_INTERVAL_ONE; + case 2: return D3DPRESENT_INTERVAL_TWO; + case 3: return D3DPRESENT_INTERVAL_THREE; + case 4: return D3DPRESENT_INTERVAL_FOUR; + default: UNREACHABLE(); + } + + return D3DPRESENT_INTERVAL_DEFAULT; +#endif +} + +EGLint SwapChain9::resize(int backbufferWidth, int backbufferHeight) +{ + // D3D9 does not support resizing swap chains without recreating them + return reset(backbufferWidth, backbufferHeight, mSwapInterval); +} + +EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) +{ + IDirect3DDevice9 *device = mRenderer->getDevice(); + + if (device == NULL) + { + return EGL_BAD_ACCESS; + } + + // Evict all non-render target textures to system memory and release all resources + // before reallocating them to free up as much video memory as possible. + device->EvictManagedResources(); + + HRESULT result; + + // Release specific resources to free up memory for the new render target, while the + // old render target still exists for the purpose of preserving its contents. + SafeRelease(mSwapChain); + SafeRelease(mBackBuffer); + SafeRelease(mOffscreenTexture); + SafeRelease(mDepthStencil); + + HANDLE *pShareHandle = NULL; + if (!mWindow && mRenderer->getShareHandleSupport()) + { + pShareHandle = &mShareHandle; + } + + result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, + gl_d3d9::GetTextureFormat(mBackBufferFormat), + D3DPOOL_DEFAULT, &mOffscreenTexture, pShareHandle); + if (FAILED(result)) + { + ERR("Could not create offscreen texture: %08lX", result); + release(); + + if (d3d9::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + IDirect3DSurface9 *oldRenderTarget = mRenderTarget; + + result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget); + ASSERT(SUCCEEDED(result)); + + if (oldRenderTarget) + { + RECT rect = + { + 0, 0, + mWidth, mHeight + }; + + if (rect.right > static_cast(backbufferWidth)) + { + rect.right = backbufferWidth; + } + + if (rect.bottom > static_cast(backbufferHeight)) + { + rect.bottom = backbufferHeight; + } + + mRenderer->endScene(); + + result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE); + ASSERT(SUCCEEDED(result)); + + SafeRelease(oldRenderTarget); + } + + if (mWindow) + { + D3DPRESENT_PARAMETERS presentParameters = {0}; + presentParameters.AutoDepthStencilFormat = gl_d3d9::GetRenderFormat(mDepthBufferFormat); + presentParameters.BackBufferCount = 1; + presentParameters.BackBufferFormat = gl_d3d9::GetRenderFormat(mBackBufferFormat); + presentParameters.EnableAutoDepthStencil = FALSE; + presentParameters.Flags = 0; + presentParameters.hDeviceWindow = mWindow; + presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented + presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented + presentParameters.PresentationInterval = convertInterval(swapInterval); + presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; + presentParameters.Windowed = TRUE; + presentParameters.BackBufferWidth = backbufferWidth; + presentParameters.BackBufferHeight = backbufferHeight; + + // http://crbug.com/140239 + // http://crbug.com/143434 + // + // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width + // when using the integrated Intel. This rounds the width up rather than down. + // + // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID + // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur. + if (mRenderer->getAdapterVendor() == VENDOR_ID_INTEL) + { + presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64; + } + + result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST); + + ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); + release(); + + if (d3d9::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + + result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); + ASSERT(SUCCEEDED(result)); + InvalidateRect(mWindow, NULL, FALSE); + } + + if (mDepthBufferFormat != GL_NONE) + { + result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, + gl_d3d9::GetRenderFormat(mDepthBufferFormat), + D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL); + + ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); + release(); + + if (d3d9::isDeviceLostError(result)) + { + return EGL_CONTEXT_LOST; + } + else + { + return EGL_BAD_ALLOC; + } + } + } + + mWidth = backbufferWidth; + mHeight = backbufferHeight; + mSwapInterval = swapInterval; + + return EGL_SUCCESS; +} + +// parameters should be validated/clamped by caller +EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint) +{ + if (!mSwapChain) + { + return EGL_SUCCESS; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + + // Disable all pipeline operations + device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); + device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); + device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); + device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); + device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); + device->SetRenderState(D3DRS_STENCILENABLE, FALSE); + device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); + device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); + device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); + device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); + device->SetPixelShader(NULL); + device->SetVertexShader(NULL); + + device->SetRenderTarget(0, mBackBuffer); + device->SetDepthStencilSurface(NULL); + + device->SetTexture(0, mOffscreenTexture); + device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); + device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); + device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); + + for (UINT streamIndex = 0; streamIndex < gl::MAX_VERTEX_ATTRIBS; streamIndex++) + { + device->SetStreamSourceFreq(streamIndex, 1); + } + + D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; + device->SetViewport(&viewport); + + float x1 = x - 0.5f; + float y1 = (mHeight - y - height) - 0.5f; + float x2 = (x + width) - 0.5f; + float y2 = (mHeight - y) - 0.5f; + + float u1 = x / float(mWidth); + float v1 = y / float(mHeight); + float u2 = (x + width) / float(mWidth); + float v2 = (y + height) / float(mHeight); + + float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2}, + {x2, y1, 0.0f, 1.0f, u2, v2}, + {x2, y2, 0.0f, 1.0f, u2, v1}, + {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v + + mRenderer->startScene(); + device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); + mRenderer->endScene(); + + device->SetTexture(0, NULL); + + RECT rect = + { + x, mHeight - y - height, + x + width, mHeight - y + }; + + HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); + + mRenderer->markAllStateDirty(); + + if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) + { + return EGL_BAD_ALLOC; + } + + // On Windows 8 systems, IDirect3DSwapChain9::Present sometimes returns 0x88760873 when the windows is + // in the process of entering/exiting fullscreen. This code doesn't seem to have any documentation. The + // device appears to be ok after emitting this error so simply return a failure to swap. + if (result == 0x88760873) + { + return EGL_BAD_MATCH; + } + + // http://crbug.com/313210 + // If our swap failed, trigger a device lost event. Resetting will work around an AMD-specific + // device removed bug with lost contexts when reinstalling drivers. + if (FAILED(result)) + { + mRenderer->notifyDeviceLost(); + return EGL_CONTEXT_LOST; + } + + return EGL_SUCCESS; +} + +// Increments refcount on surface. +// caller must Release() the returned surface +// TODO: remove the AddRef to match SwapChain11 +IDirect3DSurface9 *SwapChain9::getRenderTarget() +{ + if (mRenderTarget) + { + mRenderTarget->AddRef(); + } + + return mRenderTarget; +} + +// Increments refcount on surface. +// caller must Release() the returned surface +// TODO: remove the AddRef to match SwapChain11 +IDirect3DSurface9 *SwapChain9::getDepthStencil() +{ + if (mDepthStencil) + { + mDepthStencil->AddRef(); + } + + return mDepthStencil; +} + +// Increments refcount on texture. +// caller must Release() the returned texture +// TODO: remove the AddRef to match SwapChain11 +IDirect3DTexture9 *SwapChain9::getOffscreenTexture() +{ + if (mOffscreenTexture) + { + mOffscreenTexture->AddRef(); + } + + return mOffscreenTexture; +} + +SwapChain9 *SwapChain9::makeSwapChain9(SwapChain *swapChain) +{ + ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain9*, swapChain)); + return static_cast(swapChain); +} + +void SwapChain9::recreate() +{ + if (!mSwapChain) + { + return; + } + + IDirect3DDevice9 *device = mRenderer->getDevice(); + if (device == NULL) + { + return; + } + + D3DPRESENT_PARAMETERS presentParameters; + HRESULT result = mSwapChain->GetPresentParameters(&presentParameters); + ASSERT(SUCCEEDED(result)); + + IDirect3DSwapChain9* newSwapChain = NULL; + result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain); + if (FAILED(result)) + { + return; + } + + SafeRelease(mSwapChain); + mSwapChain = newSwapChain; + + SafeRelease(mBackBuffer); + result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); + ASSERT(SUCCEEDED(result)); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h new file mode 100644 index 0000000000..4d756f80d1 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h @@ -0,0 +1,55 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// SwapChain9.h: Defines a back-end specific class for the D3D9 swap chain. + +#ifndef LIBGLESV2_RENDERER_SWAPCHAIN9_H_ +#define LIBGLESV2_RENDERER_SWAPCHAIN9_H_ + +#include "common/angleutils.h" +#include "libGLESv2/renderer/SwapChain.h" + +namespace rx +{ +class Renderer9; + +class SwapChain9 : public SwapChain +{ + public: + SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle, + GLenum backBufferFormat, GLenum depthBufferFormat); + virtual ~SwapChain9(); + + EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); + virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); + virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height, EGLint); + virtual void recreate(); + + virtual IDirect3DSurface9 *getRenderTarget(); + virtual IDirect3DSurface9 *getDepthStencil(); + virtual IDirect3DTexture9 *getOffscreenTexture(); + + static SwapChain9 *makeSwapChain9(SwapChain *swapChain); + + private: + DISALLOW_COPY_AND_ASSIGN(SwapChain9); + + void release(); + + Renderer9 *mRenderer; + EGLint mHeight; + EGLint mWidth; + EGLint mSwapInterval; + + IDirect3DSwapChain9 *mSwapChain; + IDirect3DSurface9 *mBackBuffer; + IDirect3DSurface9 *mRenderTarget; + IDirect3DSurface9 *mDepthStencil; + IDirect3DTexture9* mOffscreenTexture; +}; + +} +#endif // LIBGLESV2_RENDERER_SWAPCHAIN9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp new file mode 100644 index 0000000000..b065ee80fe --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp @@ -0,0 +1,307 @@ +#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 +// found in the LICENSE file. +// + +// TextureStorage9.cpp: Implements the abstract rx::TextureStorage9 class and its concrete derived +// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the +// D3D9 texture. + +#include "libGLESv2/main.h" +#include "libGLESv2/renderer/d3d/TextureD3D.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.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/Texture.h" + +namespace rx +{ +TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage) + : mTopLevel(0), + mRenderer(Renderer9::makeRenderer9(renderer)), + mD3DUsage(usage), + mD3DPool(mRenderer->getTexturePool(usage)) +{ +} + +TextureStorage9::~TextureStorage9() +{ +} + +TextureStorage9 *TextureStorage9::makeTextureStorage9(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9*, storage)); + return static_cast(storage); +} + +DWORD TextureStorage9::GetTextureUsage(GLenum internalformat, bool renderTarget) +{ + DWORD d3dusage = 0; + + if (gl::GetDepthBits(internalformat) > 0 || + gl::GetStencilBits(internalformat) > 0) + { + d3dusage |= D3DUSAGE_DEPTHSTENCIL; + } + else if (renderTarget && (gl_d3d9::GetRenderFormat(internalformat) != D3DFMT_UNKNOWN)) + { + d3dusage |= D3DUSAGE_RENDERTARGET; + } + + return d3dusage; +} + + +bool TextureStorage9::isRenderTarget() const +{ + return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0; +} + +bool TextureStorage9::isManaged() const +{ + return (mD3DPool == D3DPOOL_MANAGED); +} + +D3DPOOL TextureStorage9::getPool() const +{ + return mD3DPool; +} + +DWORD TextureStorage9::getUsage() const +{ + return mD3DUsage; +} + +int TextureStorage9::getTopLevel() const +{ + return mTopLevel; +} + +int TextureStorage9::getLevelCount() const +{ + return getBaseTexture() ? (getBaseTexture()->GetLevelCount() - getTopLevel()) : 0; +} + +TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain) + : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET) +{ + IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture(); + mTexture = surfaceTexture; + mRenderTarget = NULL; + + initializeRenderTarget(); +} + +TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) + : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) +{ + mTexture = NULL; + mRenderTarget = NULL; + // if the width or height is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (width > 0 && height > 0) + { + IDirect3DDevice9 *device = mRenderer->getDevice(); + D3DFORMAT format = gl_d3d9::GetTextureFormat(internalformat); + d3d9::MakeValidSize(false, format, &width, &height, &mTopLevel); + UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels; + + HRESULT result = device->CreateTexture(width, height, creationLevels, getUsage(), format, getPool(), &mTexture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + gl::error(GL_OUT_OF_MEMORY); + } + } + + initializeRenderTarget(); +} + +TextureStorage9_2D::~TextureStorage9_2D() +{ + SafeRelease(mTexture); + SafeDelete(mRenderTarget); +} + +TextureStorage9_2D *TextureStorage9_2D::makeTextureStorage9_2D(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_2D*, storage)); + return static_cast(storage); +} + +// Increments refcount on surface. +// caller must Release() the returned surface +IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty) +{ + IDirect3DSurface9 *surface = NULL; + + if (mTexture) + { + HRESULT result = mTexture->GetSurfaceLevel(level + mTopLevel, &surface); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + + // With managed textures the driver needs to be informed of updates to the lower mipmap levels + if (level + mTopLevel != 0 && isManaged() && dirty) + { + mTexture->AddDirtyRect(NULL); + } + } + + return surface; +} + +RenderTarget *TextureStorage9_2D::getRenderTarget(int level) +{ + return mRenderTarget; +} + +void TextureStorage9_2D::generateMipmap(int level) +{ + IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false); + IDirect3DSurface9 *lower = getSurfaceLevel(level, true); + + if (upper != NULL && lower != NULL) + { + mRenderer->boxFilter(upper, lower); + } + + SafeRelease(upper); + SafeRelease(lower); +} + +IDirect3DBaseTexture9 *TextureStorage9_2D::getBaseTexture() const +{ + return mTexture; +} + +void TextureStorage9_2D::initializeRenderTarget() +{ + ASSERT(mRenderTarget == NULL); + + if (mTexture != NULL && isRenderTarget()) + { + IDirect3DSurface9 *surface = getSurfaceLevel(0, false); + + mRenderTarget = new RenderTarget9(mRenderer, surface); + } +} + +TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels) + : TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget)) +{ + mTexture = NULL; + for (int i = 0; i < 6; ++i) + { + mRenderTarget[i] = NULL; + } + + // if the size is not positive this should be treated as an incomplete texture + // we handle that here by skipping the d3d texture creation + if (size > 0) + { + IDirect3DDevice9 *device = mRenderer->getDevice(); + int height = size; + D3DFORMAT format = gl_d3d9::GetTextureFormat(internalformat); + d3d9::MakeValidSize(false, format, &size, &height, &mTopLevel); + UINT creationLevels = (levels == 0) ? 0 : mTopLevel + levels; + + HRESULT result = device->CreateCubeTexture(size, creationLevels, getUsage(), format, getPool(), &mTexture, NULL); + + if (FAILED(result)) + { + ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); + gl::error(GL_OUT_OF_MEMORY); + } + } + + initializeRenderTarget(); +} + +TextureStorage9_Cube::~TextureStorage9_Cube() +{ + SafeRelease(mTexture); + + for (int i = 0; i < 6; ++i) + { + SafeDelete(mRenderTarget[i]); + } +} + +TextureStorage9_Cube *TextureStorage9_Cube::makeTextureStorage9_Cube(TextureStorage *storage) +{ + ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_Cube*, storage)); + return static_cast(storage); +} + +// Increments refcount on surface. +// caller must Release() the returned surface +IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty) +{ + IDirect3DSurface9 *surface = NULL; + + if (mTexture) + { + D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget); + HRESULT result = mTexture->GetCubeMapSurface(face, level + mTopLevel, &surface); + UNUSED_ASSERTION_VARIABLE(result); + ASSERT(SUCCEEDED(result)); + + // With managed textures the driver needs to be informed of updates to the lower mipmap levels + if (level != 0 && isManaged() && dirty) + { + mTexture->AddDirtyRect(face, NULL); + } + } + + return surface; +} + +RenderTarget *TextureStorage9_Cube::getRenderTargetFace(GLenum faceTarget, int level) +{ + return mRenderTarget[TextureD3D_Cube::targetToIndex(faceTarget)]; +} + +void TextureStorage9_Cube::generateMipmap(int faceIndex, int 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); +} + +IDirect3DBaseTexture9 *TextureStorage9_Cube::getBaseTexture() const +{ + return mTexture; +} + +void TextureStorage9_Cube::initializeRenderTarget() +{ + if (mTexture != NULL && isRenderTarget()) + { + IDirect3DSurface9 *surface = NULL; + + for (int i = 0; i < 6; ++i) + { + ASSERT(mRenderTarget[i] == NULL); + + surface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, false); + + mRenderTarget[i] = new RenderTarget9(mRenderer, surface); + } + } +} + +} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h new file mode 100644 index 0000000000..cc7c155d34 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h @@ -0,0 +1,109 @@ +// +// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// TextureStorage9.h: Defines the abstract rx::TextureStorage9 class and its concrete derived +// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the +// D3D9 texture. + +#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ +#define LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ + +#include "libGLESv2/renderer/d3d/TextureStorage.h" +#include "common/debug.h" + +namespace rx +{ +class Renderer9; +class SwapChain9; +class RenderTarget; +class RenderTarget9; + +class TextureStorage9 : public TextureStorage +{ + public: + virtual ~TextureStorage9(); + + static TextureStorage9 *makeTextureStorage9(TextureStorage *storage); + + static DWORD GetTextureUsage(GLenum internalformat, bool renderTarget); + + D3DPOOL getPool() const; + DWORD getUsage() const; + + virtual 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 int getTopLevel() const; + virtual bool isRenderTarget() const; + virtual bool isManaged() const; + virtual int getLevelCount() const; + + protected: + int mTopLevel; + Renderer9 *mRenderer; + + TextureStorage9(Renderer *renderer, DWORD usage); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage9); + + const DWORD mD3DUsage; + const D3DPOOL mD3DPool; +}; + +class TextureStorage9_2D : public TextureStorage9 +{ + public: + TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain); + TextureStorage9_2D(Renderer *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels); + virtual ~TextureStorage9_2D(); + + static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage); + + IDirect3DSurface9 *getSurfaceLevel(int level, bool dirty); + virtual RenderTarget *getRenderTarget(int level); + virtual IDirect3DBaseTexture9 *getBaseTexture() const; + virtual void generateMipmap(int level); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage9_2D); + + void initializeRenderTarget(); + + IDirect3DTexture9 *mTexture; + RenderTarget9 *mRenderTarget; +}; + +class TextureStorage9_Cube : public TextureStorage9 +{ + public: + TextureStorage9_Cube(Renderer *renderer, GLenum internalformat, bool renderTarget, int size, int levels); + virtual ~TextureStorage9_Cube(); + + static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage); + + IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level, bool dirty); + virtual RenderTarget *getRenderTargetFace(GLenum faceTarget, int level); + virtual IDirect3DBaseTexture9 *getBaseTexture() const; + virtual void generateMipmap(int faceIndex, int level); + + private: + DISALLOW_COPY_AND_ASSIGN(TextureStorage9_Cube); + + void initializeRenderTarget(); + + IDirect3DCubeTexture9 *mTexture; + RenderTarget9 *mRenderTarget[6]; +}; + +} + +#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ + diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h new file mode 100644 index 0000000000..66a6c64d81 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h @@ -0,0 +1,43 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexArray9.h: Defines the rx::VertexArray9 class which implements rx::VertexArrayImpl. + +#ifndef LIBGLESV2_RENDERER_VERTEXARRAY9_H_ +#define LIBGLESV2_RENDERER_VERTEXARRAY9_H_ + +#include "libGLESv2/renderer/VertexArrayImpl.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" + +namespace rx +{ +class Renderer9; + +class VertexArray9 : public VertexArrayImpl +{ + public: + VertexArray9(rx::Renderer9 *renderer) + : VertexArrayImpl(), + mRenderer(renderer) + { + } + + virtual ~VertexArray9() { } + + virtual void setElementArrayBuffer(const gl::Buffer *buffer) { } + virtual void setAttribute(size_t idx, const gl::VertexAttribute &attr) { } + virtual void setAttributeDivisor(size_t idx, GLuint divisor) { } + virtual void enableAttribute(size_t idx, bool enabledState) { } + + private: + DISALLOW_COPY_AND_ASSIGN(VertexArray9); + + rx::Renderer9 *mRenderer; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXARRAY9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp new file mode 100644 index 0000000000..d260640dbe --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp @@ -0,0 +1,252 @@ +#include "precompiled.h" +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation. + +#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.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) +{ + mVertexBuffer = NULL; + mBufferSize = 0; + mDynamicUsage = false; +} + +VertexBuffer9::~VertexBuffer9() +{ + SafeRelease(mVertexBuffer); +} + +bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) +{ + SafeRelease(mVertexBuffer); + + updateSerial(); + + if (size > 0) + { + DWORD flags = D3DUSAGE_WRITEONLY; + if (dynamicUsage) + { + flags |= D3DUSAGE_DYNAMIC; + } + + HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer); + + if (FAILED(result)) + { + ERR("Out of memory allocating a vertex buffer of size %lu.", size); + return false; + } + } + + mBufferSize = size; + mDynamicUsage = dynamicUsage; + return true; +} + +VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer) +{ + ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer)); + return static_cast(vertexBuffer); +} + +bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData ¤tValue, + GLint start, GLsizei count, GLsizei instances, unsigned int offset) +{ + if (mVertexBuffer) + { + gl::Buffer *buffer = attrib.buffer.get(); + + int inputStride = gl::ComputeVertexAttributeStride(attrib); + int elementSize = gl::ComputeVertexAttributeTypeSize(attrib); + + DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; + + void *mapPtr = NULL; + + unsigned int mapSize; + if (!spaceRequired(attrib, count, instances, &mapSize)) + { + return false; + } + + HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags); + + if (FAILED(result)) + { + ERR("Lock failed with error 0x%08x", result); + return false; + } + + const char *input = NULL; + if (attrib.enabled) + { + if (buffer) + { + BufferImpl *storage = buffer->getImplementation(); + input = static_cast(storage->getData()) + static_cast(attrib.offset); + } + else + { + input = static_cast(attrib.pointer); + } + } + else + { + input = reinterpret_cast(currentValue.FloatValues); + } + + if (instances == 0 || attrib.divisor == 0) + { + input += inputStride * start; + } + + gl::VertexFormat vertexFormat(attrib, currentValue.Type); + 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); + } + + mVertexBuffer->Unlock(); + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, + unsigned int *outSpaceRequired) const +{ + return spaceRequired(attrib, count, instances, outSpaceRequired); +} + +unsigned int VertexBuffer9::getBufferSize() const +{ + return mBufferSize; +} + +bool VertexBuffer9::setBufferSize(unsigned int size) +{ + if (size > mBufferSize) + { + return initialize(size, mDynamicUsage); + } + else + { + return true; + } +} + +bool VertexBuffer9::discard() +{ + if (mVertexBuffer) + { + void *dummy; + HRESULT result; + + result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); + if (FAILED(result)) + { + ERR("Discard lock failed with error 0x%08x", result); + return false; + } + + result = mVertexBuffer->Unlock(); + if (FAILED(result)) + { + ERR("Discard unlock failed with error 0x%08x", result); + return false; + } + + return true; + } + else + { + ERR("Vertex buffer not initialized."); + return false; + } +} + +IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const +{ + return mVertexBuffer; +} + +bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, + unsigned int *outSpaceRequired) +{ + gl::VertexFormat vertexFormat(attrib, GL_FLOAT); + unsigned int elementSize = d3d9::GetVertexElementSize(vertexFormat); + + if (attrib.enabled) + { + unsigned int elementCount = 0; + if (instances == 0 || attrib.divisor == 0) + { + elementCount = count; + } + 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; + } + } + + if (elementSize <= std::numeric_limits::max() / elementCount) + { + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * elementCount; + } + return true; + } + else + { + return false; + } + } + else + { + const unsigned int elementSize = 4; + if (outSpaceRequired) + { + *outSpaceRequired = elementSize * 4; + } + return true; + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h new file mode 100644 index 0000000000..fc4b6b6d26 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h @@ -0,0 +1,54 @@ +// +// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexBuffer9.h: Defines the D3D9 VertexBuffer implementation. + +#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ +#define LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ + +#include "libGLESv2/renderer/d3d/VertexBuffer.h" + +namespace rx +{ +class Renderer9; + +class VertexBuffer9 : public VertexBuffer +{ + public: + explicit VertexBuffer9(rx::Renderer9 *const renderer); + virtual ~VertexBuffer9(); + + virtual bool initialize(unsigned int size, bool dynamicUsage); + + static VertexBuffer9 *makeVertexBuffer9(VertexBuffer *vertexBuffer); + + virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, 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 unsigned int getBufferSize() const; + virtual bool setBufferSize(unsigned int size); + virtual bool discard(); + + IDirect3DVertexBuffer9 *getBuffer() const; + + private: + DISALLOW_COPY_AND_ASSIGN(VertexBuffer9); + + rx::Renderer9 *const mRenderer; + + IDirect3DVertexBuffer9 *mVertexBuffer; + unsigned int mBufferSize; + bool mDynamicUsage; + + static bool spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, + unsigned int *outSpaceRequired); +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp new file mode 100644 index 0000000000..303d8ad299 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp @@ -0,0 +1,216 @@ +#include "precompiled.h" +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations. + +#include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/VertexAttribute.h" +#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h" +#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" + +namespace rx +{ + +VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0) +{ + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + mVertexDeclCache[i].vertexDeclaration = NULL; + mVertexDeclCache[i].lruCount = 0; + } + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mAppliedVBs[i].serial = 0; + } + + mLastSetVDecl = NULL; + mInstancingEnabled = true; +} + +VertexDeclarationCache::~VertexDeclarationCache() +{ + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + SafeRelease(mVertexDeclCache[i].vertexDeclaration); + } +} + +GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw) +{ + *repeatDraw = 1; + + int indexedAttribute = gl::MAX_VERTEX_ATTRIBS; + int instancedAttribute = gl::MAX_VERTEX_ATTRIBS; + + if (instances > 0) + { + // Find an indexed attribute to be mapped to D3D stream 0 + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (attributes[i].active) + { + if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor == 0) + { + indexedAttribute = i; + } + else if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor != 0) + { + instancedAttribute = i; + } + if (indexedAttribute != gl::MAX_VERTEX_ATTRIBS && instancedAttribute != gl::MAX_VERTEX_ATTRIBS) + break; // Found both an indexed and instanced attribute + } + } + + if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS) + { + return GL_INVALID_OPERATION; + } + } + + D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1]; + D3DVERTEXELEMENT9 *element = &elements[0]; + + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + if (attributes[i].active) + { + // Directly binding the storage buffer is not supported for d3d9 + ASSERT(attributes[i].storage == NULL); + + int stream = i; + + if (instances > 0) + { + // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced. + if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS) + { + *repeatDraw = instances; + } + else + { + if (i == indexedAttribute) + { + stream = 0; + } + else if (i == 0) + { + stream = indexedAttribute; + } + + UINT frequency = 1; + + if (attributes[i].divisor == 0) + { + frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances; + } + else + { + frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor; + } + + device->SetStreamSourceFreq(stream, frequency); + mInstancingEnabled = true; + } + } + + VertexBuffer9 *vertexBuffer = VertexBuffer9::makeVertexBuffer9(attributes[i].vertexBuffer); + + if (mAppliedVBs[stream].serial != attributes[i].serial || + mAppliedVBs[stream].stride != attributes[i].stride || + mAppliedVBs[stream].offset != attributes[i].offset) + { + device->SetStreamSource(stream, vertexBuffer->getBuffer(), attributes[i].offset, attributes[i].stride); + mAppliedVBs[stream].serial = attributes[i].serial; + mAppliedVBs[stream].stride = attributes[i].stride; + mAppliedVBs[stream].offset = attributes[i].offset; + } + + gl::VertexFormat vertexFormat(*attributes[i].attribute, GL_FLOAT); + + element->Stream = stream; + element->Offset = 0; + element->Type = d3d9::GetNativeVertexFormat(vertexFormat); + element->Method = D3DDECLMETHOD_DEFAULT; + element->Usage = D3DDECLUSAGE_TEXCOORD; + element->UsageIndex = programBinary->getSemanticIndex(i); + element++; + } + } + + if (instances == 0 || instancedAttribute == gl::MAX_VERTEX_ATTRIBS) + { + if (mInstancingEnabled) + { + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + device->SetStreamSourceFreq(i, 1); + } + + mInstancingEnabled = false; + } + } + + static const D3DVERTEXELEMENT9 end = D3DDECL_END(); + *(element++) = end; + + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + VertexDeclCacheEntry *entry = &mVertexDeclCache[i]; + if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration) + { + entry->lruCount = ++mMaxLru; + if(entry->vertexDeclaration != mLastSetVDecl) + { + device->SetVertexDeclaration(entry->vertexDeclaration); + mLastSetVDecl = entry->vertexDeclaration; + } + + return GL_NO_ERROR; + } + } + + VertexDeclCacheEntry *lastCache = mVertexDeclCache; + + for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) + { + if (mVertexDeclCache[i].lruCount < lastCache->lruCount) + { + lastCache = &mVertexDeclCache[i]; + } + } + + if (lastCache->vertexDeclaration != NULL) + { + SafeRelease(lastCache->vertexDeclaration); + // mLastSetVDecl is set to the replacement, so we don't have to worry + // about it. + } + + memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)); + device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration); + device->SetVertexDeclaration(lastCache->vertexDeclaration); + mLastSetVDecl = lastCache->vertexDeclaration; + lastCache->lruCount = ++mMaxLru; + + return GL_NO_ERROR; +} + +void VertexDeclarationCache::markStateDirty() +{ + for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) + { + mAppliedVBs[i].serial = 0; + } + + mLastSetVDecl = NULL; + mInstancingEnabled = true; // Forces it to be disabled when not used +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h new file mode 100644 index 0000000000..004e28df4f --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h @@ -0,0 +1,58 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// VertexDeclarationCache.h: Defines a helper class to construct and cache vertex declarations. + +#ifndef LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ +#define LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ + +#include "libGLESv2/renderer/d3d/VertexDataManager.h" + +namespace gl +{ +class VertexDataManager; +} + +namespace rx +{ + +class VertexDeclarationCache +{ + public: + VertexDeclarationCache(); + ~VertexDeclarationCache(); + + GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw); + + void markStateDirty(); + + private: + UINT mMaxLru; + + enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 32 }; + + struct VBData + { + unsigned int serial; + unsigned int stride; + unsigned int offset; + }; + + VBData mAppliedVBs[gl::MAX_VERTEX_ATTRIBS]; + IDirect3DVertexDeclaration9 *mLastSetVDecl; + bool mInstancingEnabled; + + struct VertexDeclCacheEntry + { + D3DVERTEXELEMENT9 cachedElements[gl::MAX_VERTEX_ATTRIBS + 1]; + UINT lruCount; + IDirect3DVertexDeclaration9 *vertexDeclaration; + } mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES]; +}; + +} + +#endif // LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp new file mode 100644 index 0000000000..f5d1da62b3 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp @@ -0,0 +1,820 @@ +#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 +// found in the LICENSE file. +// + +// formatutils9.cpp: Queries for GL image formats and their translations to D3D9 +// formats. + +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h" +#include "libGLESv2/renderer/generatemip.h" +#include "libGLESv2/renderer/loadimage.h" +#include "libGLESv2/renderer/copyimage.h" +#include "libGLESv2/renderer/vertexconversion.h" + +namespace rx +{ + +// Each GL internal format corresponds to one D3D format and data loading function. +// Due to not all formats being available all the time, some of the function/format types are wrapped +// in templates that perform format support queries on a Renderer9 object which is supplied +// when requesting the function or format. + +typedef bool(*FallbackPredicateFunction)(); + +template +static void FallbackLoad(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + if (pred()) + { + prefered(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); + } + else + { + fallback(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); + } +} + +static void UnreachableLoad(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + UNREACHABLE(); +} + +const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I', 'N', 'T', 'Z'))); +const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N', 'U', 'L', 'L'))); + +struct D3D9FormatInfo +{ + D3DFORMAT mTexFormat; + D3DFORMAT mRenderFormat; + LoadImageFunction mLoadFunction; + + D3D9FormatInfo() + : mTexFormat(D3DFMT_NULL), mRenderFormat(D3DFMT_NULL), mLoadFunction(NULL) + { } + + D3D9FormatInfo(D3DFORMAT textureFormat, D3DFORMAT renderFormat, LoadImageFunction loadFunc) + : mTexFormat(textureFormat), mRenderFormat(renderFormat), mLoadFunction(loadFunc) + { } +}; + +typedef std::pair D3D9FormatPair; +typedef std::map D3D9FormatMap; + +static D3D9FormatMap BuildD3D9FormatMap() +{ + D3D9FormatMap 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 ))); + + return map; +} + +static bool GetD3D9FormatInfo(GLenum internalFormat, D3D9FormatInfo *outFormatInfo) +{ + 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 +{ + GLuint mPixelBits; + GLuint mBlockWidth; + GLuint mBlockHeight; + GLenum mInternalFormat; + + MipGenerationFunction mMipGenerationFunction; + ColorReadFunction mColorReadFunction; + + D3DFormatInfo() + : mPixelBits(0), mBlockWidth(0), mBlockHeight(0), mInternalFormat(GL_NONE), mMipGenerationFunction(NULL), + mColorReadFunction(NULL) + { } + + 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) + { } +}; + +typedef std::pair D3D9FormatInfoPair; +typedef std::map D3D9FormatInfoMap; + +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 ))); + + return map; +} + +static const D3D9FormatInfoMap &GetD3D9FormatInfoMap() +{ + 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; + } + else + { + return false; + } +} +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; + +static InternalFormatInitialzerMap BuildInternalFormatInitialzerMap() +{ + InternalFormatInitialzerMap map; + + 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; +} + +namespace d3d9 +{ + +MipGenerationFunction GetMipGenerationFunction(D3DFORMAT format) +{ + D3DFormatInfo d3dFormatInfo; + if (GetD3D9FormatInfo(format, &d3dFormatInfo)) + { + return d3dFormatInfo.mMipGenerationFunction; + } + else + { + UNREACHABLE(); + return NULL; + } +} + +LoadImageFunction GetImageLoadFunction(GLenum internalFormat) +{ + D3D9FormatInfo d3d9FormatInfo; + if (GetD3D9FormatInfo(internalFormat, &d3d9FormatInfo)) + { + return d3d9FormatInfo.mLoadFunction; + } + else + { + UNREACHABLE(); + return NULL; + } +} + +GLuint GetFormatPixelBytes(D3DFORMAT format) +{ + D3DFormatInfo d3dFormatInfo; + if (GetD3D9FormatInfo(format, &d3dFormatInfo)) + { + return d3dFormatInfo.mPixelBits / 8; + } + else + { + UNREACHABLE(); + return 0; + } +} + +GLuint GetBlockWidth(D3DFORMAT format) +{ + D3DFormatInfo d3dFormatInfo; + if (GetD3D9FormatInfo(format, &d3dFormatInfo)) + { + return d3dFormatInfo.mBlockWidth; + } + else + { + UNREACHABLE(); + return 0; + } +} + +GLuint GetBlockHeight(D3DFORMAT format) +{ + D3DFormatInfo d3dFormatInfo; + if (GetD3D9FormatInfo(format, &d3dFormatInfo)) + { + return d3dFormatInfo.mBlockHeight; + } + else + { + UNREACHABLE(); + return 0; + } +} + +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; + + return (d3dFormatInfo.mPixelBits * numBlocksWide * numBlocksHight) / 8; + } + else + { + UNREACHABLE(); + return 0; + } +} + +void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) +{ + D3DFormatInfo d3dFormatInfo; + if (GetD3D9FormatInfo(format, &d3dFormatInfo)) + { + int upsampleCount = 0; + + GLsizei blockWidth = d3dFormatInfo.mBlockWidth; + GLsizei blockHeight = d3dFormatInfo.mBlockHeight; + + // 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; + } +} + +const D3DFormatSet &GetAllUsedD3DFormats() +{ + static const D3DFormatSet formatSet = BuildAllD3DFormatSet(); + return formatSet; +} + +ColorReadFunction GetColorReadFunction(D3DFORMAT format) +{ + D3DFormatInfo d3dFormatInfo; + if (GetD3D9FormatInfo(format, &d3dFormatInfo)) + { + return d3dFormatInfo.mColorReadFunction; + } + else + { + UNREACHABLE(); + return NULL; + } +} + +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) +{ + switch (declType) + { + case D3DDECLTYPE_FLOAT1: return GL_FLOAT; + case D3DDECLTYPE_FLOAT2: return GL_FLOAT; + case D3DDECLTYPE_FLOAT3: return GL_FLOAT; + case D3DDECLTYPE_FLOAT4: return GL_FLOAT; + case D3DDECLTYPE_UBYTE4: return GL_UNSIGNED_INT; + case D3DDECLTYPE_SHORT2: return GL_INT; + case D3DDECLTYPE_SHORT4: return GL_INT; + case D3DDECLTYPE_UBYTE4N: return GL_UNSIGNED_NORMALIZED; + case D3DDECLTYPE_SHORT4N: return GL_SIGNED_NORMALIZED; + case D3DDECLTYPE_USHORT4N: return GL_UNSIGNED_NORMALIZED; + case D3DDECLTYPE_SHORT2N: return GL_SIGNED_NORMALIZED; + case D3DDECLTYPE_USHORT2N: return GL_UNSIGNED_NORMALIZED; + default: UNREACHABLE(); return GL_NONE; + } +} + +// Attribute format conversion +enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; + +struct 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; +}; + +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) +// BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm) +// UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast) +// UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize) +// SHORT SHORT (Identity) +// SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize) +// UNSIGNED_SHORT FLOAT (Cast) +// UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize) +// FIXED (not in WebGL) FLOAT (FixedToFloat) +// FLOAT FLOAT (Identity) + +// GLToCType maps from GL type (as GLenum) to the C typedef. +template struct GLToCType { }; + +template <> struct GLToCType { typedef GLbyte type; }; +template <> struct GLToCType { typedef GLubyte type; }; +template <> struct GLToCType { typedef GLshort type; }; +template <> struct GLToCType { typedef GLushort type; }; +template <> struct GLToCType { typedef GLuint type; }; +template <> struct GLToCType { typedef GLfloat type; }; + +// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.) +enum D3DVertexType +{ + D3DVT_FLOAT, + D3DVT_SHORT, + D3DVT_SHORT_NORM, + D3DVT_UBYTE, + D3DVT_UBYTE_NORM, + D3DVT_USHORT_NORM +}; + +// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type. +template struct D3DToCType { }; + +template <> struct D3DToCType { typedef float type; }; +template <> struct D3DToCType { typedef short type; }; +template <> struct D3DToCType { typedef short type; }; +template <> struct D3DToCType { typedef unsigned char type; }; +template <> struct D3DToCType { typedef unsigned char type; }; +template <> struct D3DToCType { typedef unsigned short type; }; + +// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size. +template struct WidenRule { }; + +template struct WidenRule : NoWiden { }; +template struct WidenRule : WidenToEven { }; +template struct WidenRule : WidenToEven { }; +template struct WidenRule : WidenToFour { }; +template struct WidenRule : WidenToFour { }; +template struct WidenRule : WidenToEven { }; + +// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination. +template struct VertexTypeFlags { }; + +template +struct VertexTypeFlagsHelper +{ + enum { capflag = _capflag }; + enum { declflag = _declflag }; +}; + +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; +template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; + + +// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums). +template struct VertexTypeMapping { }; + +template +struct VertexTypeMappingBase +{ + enum { preferred = Preferred }; + enum { fallback = Fallback }; +}; + +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Normalize +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity, Cast +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity, Normalize +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast, Normalize +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast +template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast, Normalize +template struct VertexTypeMapping : VertexTypeMappingBase { }; // FixedToFloat +template struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity + + +// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat). +// The conversion rules themselves are defined in vertexconversion.h. + +// Almost all cases are covered by Cast (including those that are actually Identity since Cast knows it's an identity mapping). +template +struct ConversionRule : Cast::type, typename D3DToCType::type> { }; + +// All conversions from normalized types to float use the Normalize operator. +template struct ConversionRule : Normalize::type> { }; + +// Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules. +template <> struct ConversionRule : FixedToFloat { }; +template <> struct ConversionRule : FixedToFloat { }; + +// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1) +// whether it is normalized or not. +template struct DefaultVertexValuesStage2 { }; + +template struct DefaultVertexValuesStage2 : NormalizedDefaultValues { }; +template struct DefaultVertexValuesStage2 : SimpleDefaultValues { }; + +// Work out the default value rule for a D3D type (expressed as the C type) and +template struct DefaultVertexValues : DefaultVertexValuesStage2 { }; +template struct DefaultVertexValues : SimpleDefaultValues { }; + +// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion. +// The fallback conversion produces an output that all D3D9 devices must support. +template struct UsePreferred { enum { type = T::preferred }; }; +template struct UseFallback { enum { type = T::fallback }; }; + +// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion, +// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag +// and the D3DDECLTYPE member needed for the vertex declaration in declflag. +template class PreferenceRule> +struct Converter + : VertexDataConverter::type, + WidenRule >::type, size>, + ConversionRule >::type>, + DefaultVertexValues >::type>::type, normalized > > +{ +private: + enum { d3dtype = PreferenceRule< VertexTypeMapping >::type }; + enum { d3dsize = WidenRule::finalWidth }; + +public: + enum { capflag = VertexTypeFlags::capflag }; + enum { declflag = VertexTypeFlags::declflag }; +}; + +// Initialize a TranslationInfo +#define TRANSLATION(type, norm, size, preferred) \ + { \ + Converter::identity, \ + Converter::finalSize, \ + Converter::convertArray, \ + static_cast(Converter::declflag) \ + } + +#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \ + { \ + Converter::capflag, \ + TRANSLATION(type, norm, size, UsePreferred), \ + TRANSLATION(type, norm, size, UseFallback) \ + } + +#define TRANSLATIONS_FOR_TYPE(type) \ + { \ + { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ + { TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) }, \ + } + +#define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \ + { \ + { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ + { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ + } + +const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1] +{ + TRANSLATIONS_FOR_TYPE(GL_BYTE), + TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE), + TRANSLATIONS_FOR_TYPE(GL_SHORT), + TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT), + TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED), + TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT) +}; + +void InitializeVertexTranslations(const rx::Renderer9 *renderer) +{ + DWORD declTypes = renderer->getCapsDeclTypes(); + + for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++) + { + for (unsigned int j = 0; j < 2; j++) + { + for (unsigned int k = 0; k < 4; k++) + { + if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0) + { + mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion; + } + else + { + mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion; + } + } + } + } +} + +unsigned int typeIndex(GLenum type) +{ + switch (type) + { + case GL_BYTE: return 0; + case GL_UNSIGNED_BYTE: return 1; + case GL_SHORT: return 2; + case GL_UNSIGNED_SHORT: return 3; + case GL_FIXED: return 4; + case GL_FLOAT: return 5; + + default: UNREACHABLE(); return 5; + } +} + +const 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; +} + +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h new file mode 100644 index 0000000000..26388794e0 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h @@ -0,0 +1,77 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// formatutils9.h: Queries for GL image formats and their translations to D3D9 +// formats. + +#ifndef LIBGLESV2_RENDERER_FORMATUTILS9_H_ +#define LIBGLESV2_RENDERER_FORMATUTILS9_H_ + +#include "libGLESv2/formatutils.h" + +namespace rx +{ + +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); + +void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); + +const D3DFormatSet &GetAllUsedD3DFormats(); + +ColorReadFunction GetColorReadFunction(D3DFORMAT format); +ColorCopyFunction GetFastCopyFunction(D3DFORMAT sourceFormat, GLenum destFormat, GLenum destType); + +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 GetDeclTypeComponentType(D3DDECLTYPE declType); +int GetDeclTypeComponentCount(D3DDECLTYPE declType); +bool IsDeclTypeNormalized(D3DDECLTYPE declType); + +void InitializeVertexTranslations(const rx::Renderer9 *renderer); + +} + +namespace gl_d3d9 +{ + +D3DFORMAT GetTextureFormat(GLenum internalForma); +D3DFORMAT GetRenderFormat(GLenum internalFormat); + +D3DMULTISAMPLE_TYPE GetMultisampleType(GLsizei samples); + +bool RequiresTextureDataInitialization(GLint internalFormat); +InitializeTextureDataFunction GetTextureDataInitializationFunction(GLint internalFormat); + +} + +namespace d3d9_gl +{ + +GLenum GetInternalFormat(D3DFORMAT format); +GLsizei GetSamplesCount(D3DMULTISAMPLE_TYPE type); +bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format); + +} + +} + +#endif // LIBGLESV2_RENDERER_FORMATUTILS9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp new file mode 100644 index 0000000000..68e5378fbb --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp @@ -0,0 +1,409 @@ +#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 +// found in the LICENSE file. +// + +// renderer9_utils.cpp: Conversion functions and other utility routines +// specific to the D3D9 renderer. + +#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h" +#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h" +#include "libGLESv2/formatutils.h" +#include "common/mathutil.h" +#include "libGLESv2/Context.h" + +#include "common/debug.h" + +#include "third_party/systeminfo/SystemInfo.h" + +namespace rx +{ + +namespace gl_d3d9 +{ + +D3DCMPFUNC ConvertComparison(GLenum comparison) +{ + D3DCMPFUNC d3dComp = D3DCMP_ALWAYS; + switch (comparison) + { + case GL_NEVER: d3dComp = D3DCMP_NEVER; break; + case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break; + case GL_LESS: d3dComp = D3DCMP_LESS; break; + case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break; + case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break; + case GL_GREATER: d3dComp = D3DCMP_GREATER; break; + case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break; + case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break; + default: UNREACHABLE(); + } + + return d3dComp; +} + +D3DCOLOR ConvertColor(gl::ColorF color) +{ + return D3DCOLOR_RGBA(gl::unorm<8>(color.red), + gl::unorm<8>(color.green), + gl::unorm<8>(color.blue), + gl::unorm<8>(color.alpha)); +} + +D3DBLEND ConvertBlendFunc(GLenum blend) +{ + D3DBLEND d3dBlend = D3DBLEND_ZERO; + + switch (blend) + { + case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break; + case GL_ONE: d3dBlend = D3DBLEND_ONE; break; + case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break; + case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break; + case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break; + case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break; + case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break; + case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break; + case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break; + case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break; + case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break; + case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; + case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break; + case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; + case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break; + default: UNREACHABLE(); + } + + return d3dBlend; +} + +D3DBLENDOP ConvertBlendOp(GLenum blendOp) +{ + D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD; + + switch (blendOp) + { + case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break; + case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break; + case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break; + case GL_MIN_EXT: d3dBlendOp = D3DBLENDOP_MIN; break; + case GL_MAX_EXT: d3dBlendOp = D3DBLENDOP_MAX; break; + default: UNREACHABLE(); + } + + return d3dBlendOp; +} + +D3DSTENCILOP ConvertStencilOp(GLenum stencilOp) +{ + D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP; + + switch (stencilOp) + { + case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break; + case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break; + case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break; + case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break; + case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break; + case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break; + case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break; + case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break; + default: UNREACHABLE(); + } + + return d3dStencilOp; +} + +D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap) +{ + D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP; + + switch (wrap) + { + case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break; + case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break; + case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break; + default: UNREACHABLE(); + } + + return d3dWrap; +} + +D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace) +{ + D3DCULL cull = D3DCULL_CCW; + switch (cullFace) + { + case GL_FRONT: + cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW); + break; + case GL_BACK: + cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW); + break; + case GL_FRONT_AND_BACK: + cull = D3DCULL_NONE; // culling will be handled during draw + break; + default: UNREACHABLE(); + } + + return cull; +} + +D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace) +{ + D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X; + + switch (cubeFace) + { + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + face = D3DCUBEMAP_FACE_POSITIVE_X; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + face = D3DCUBEMAP_FACE_NEGATIVE_X; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + face = D3DCUBEMAP_FACE_POSITIVE_Y; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + face = D3DCUBEMAP_FACE_NEGATIVE_Y; + break; + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + face = D3DCUBEMAP_FACE_POSITIVE_Z; + break; + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + face = D3DCUBEMAP_FACE_NEGATIVE_Z; + break; + default: UNREACHABLE(); + } + + return face; +} + +DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha) +{ + return (red ? D3DCOLORWRITEENABLE_RED : 0) | + (green ? D3DCOLORWRITEENABLE_GREEN : 0) | + (blue ? D3DCOLORWRITEENABLE_BLUE : 0) | + (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0); +} + +D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy) +{ + if (maxAnisotropy > 1.0f) + { + return D3DTEXF_ANISOTROPIC; + } + + D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT; + switch (magFilter) + { + case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break; + case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break; + default: UNREACHABLE(); + } + + return d3dMagFilter; +} + +void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy) +{ + switch (minFilter) + { + case GL_NEAREST: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_NONE; + break; + case GL_LINEAR: + *d3dMinFilter = D3DTEXF_LINEAR; + *d3dMipFilter = D3DTEXF_NONE; + break; + case GL_NEAREST_MIPMAP_NEAREST: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_POINT; + break; + case GL_LINEAR_MIPMAP_NEAREST: + *d3dMinFilter = D3DTEXF_LINEAR; + *d3dMipFilter = D3DTEXF_POINT; + break; + case GL_NEAREST_MIPMAP_LINEAR: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_LINEAR; + break; + case GL_LINEAR_MIPMAP_LINEAR: + *d3dMinFilter = D3DTEXF_LINEAR; + *d3dMipFilter = D3DTEXF_LINEAR; + break; + default: + *d3dMinFilter = D3DTEXF_POINT; + *d3dMipFilter = D3DTEXF_NONE; + UNREACHABLE(); + } + + if (maxAnisotropy > 1.0f) + { + *d3dMinFilter = D3DTEXF_ANISOTROPIC; + } +} + +} + +namespace d3d9_gl +{ + +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) + { + 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)); + } + 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.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); + if (SUCCEEDED(result)) + { + textureCaps.sampleCounts.insert(i); + } + } + + return textureCaps; +} + +void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps, + gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions) +{ + D3DCAPS9 deviceCaps; + if (FAILED(d3d9->GetDeviceCaps(adapter, deviceType, &deviceCaps))) + { + // Can't continue with out device caps + return; + } + + D3DDISPLAYMODE currentDisplayMode; + d3d9->GetAdapterDisplayMode(adapter, ¤tDisplayMode); + + 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); + } + + // GL core feature limits + caps->maxElementIndex = static_cast(std::numeric_limits::max()); + + // 3D textures are unimplemented in D3D9 + caps->max3DTextureSize = 1; + + // Only one limit in GL, use the minimum dimension + caps->max2DTextureSize = std::min(deviceCaps.MaxTextureWidth, deviceCaps.MaxTextureHeight); + + // D3D treats cube maps as a special case of 2D textures + caps->maxCubeMapTextureSize = caps->max2DTextureSize; + + // Array textures are not available in D3D9 + caps->maxArrayTextureLayers = 1; + + // ES3-only feature + caps->maxLODBias = 0.0f; + + // No specific limits on render target size, maximum 2D texture size is equivalent + caps->maxRenderbufferSize = caps->max2DTextureSize; + + // Draw buffers are not supported in D3D9 + caps->maxDrawBuffers = 1; + caps->maxColorAttachments = 1; + + // No specific limits on viewport size, maximum 2D texture size is equivalent + caps->maxViewportWidth = caps->max2DTextureSize; + caps->maxViewportHeight = caps->maxViewportWidth; + + // Point size is clamped to 1.0f when the shader model is less than 3 + caps->minAliasedPointSize = 1.0f; + caps->maxAliasedPointSize = ((D3DSHADER_VERSION_MAJOR(deviceCaps.PixelShaderVersion) >= 3) ? deviceCaps.MaxPointSize : 1.0f); + + // Wide lines not supported + caps->minAliasedLineWidth = 1.0f; + caps->maxAliasedLineWidth = 1.0f; + + // GL extension support + extensions->setTextureExtensionSupport(*textureCapsMap); + extensions->elementIndexUint = deviceCaps.MaxVertexIndex >= (1 << 16); + extensions->packedDepthStencil = true; + extensions->getProgramBinary = true; + extensions->rgb8rgba8 = true; + extensions->readFormatBGRA = true; + extensions->pixelBufferObject = false; + extensions->mapBuffer = false; + extensions->mapBufferRange = false; + + // ATI cards on XP have problems with non-power-of-two textures. + D3DADAPTER_IDENTIFIER9 adapterId = { 0 }; + if (SUCCEEDED(d3d9->GetAdapterIdentifier(adapter, 0, &adapterId))) + { + extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && + !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && + !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && + !(isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD); + } + else + { + extensions->textureNPOT = false; + } + + extensions->drawBuffers = false; + extensions->textureStorage = true; + + // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec + extensions->textureFilterAnisotropic = (deviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) != 0 && deviceCaps.MaxAnisotropy >= 2; + extensions->maxTextureAnisotropy = static_cast(deviceCaps.MaxAnisotropy); + + // Check occlusion query support by trying to create one + IDirect3DQuery9 *occlusionQuery = NULL; + extensions->occlusionQueryBoolean = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery; + SafeRelease(occlusionQuery); + + // Check event query support by trying to create one + IDirect3DQuery9 *eventQuery = NULL; + extensions->fence = SUCCEEDED(device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery; + SafeRelease(eventQuery); + + extensions->timerQuery = false; // Unimplemented + extensions->robustness = true; + extensions->blendMinMax = true; + extensions->framebufferBlit = true; + extensions->framebufferMultisample = true; + extensions->instancedArrays = deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); + extensions->packReverseRowOrder = true; + extensions->standardDerivatives = (deviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0; + extensions->shaderTextureLOD = true; + extensions->fragDepth = true; + extensions->textureUsage = true; + extensions->translatedShaderSource = true; + extensions->colorBufferFloat = false; +} + +} + +} 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 new file mode 100644 index 0000000000..7f3c65d3e0 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h @@ -0,0 +1,65 @@ +// +// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// renderer9_utils.h: Conversion functions and other utility routines +// specific to the D3D9 renderer + +#ifndef LIBGLESV2_RENDERER_RENDERER9_UTILS_H +#define LIBGLESV2_RENDERER_RENDERER9_UTILS_H + +#include "libGLESv2/angletypes.h" +#include "libGLESv2/Caps.h" + +namespace rx +{ + +namespace gl_d3d9 +{ + +D3DCMPFUNC ConvertComparison(GLenum comparison); +D3DCOLOR ConvertColor(gl::ColorF color); +D3DBLEND ConvertBlendFunc(GLenum blend); +D3DBLENDOP ConvertBlendOp(GLenum blendOp); +D3DSTENCILOP ConvertStencilOp(GLenum stencilOp); +D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap); +D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace); +D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace); +DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha); +D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy); +void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy); + +} + +namespace d3d9_gl +{ + +void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceType, UINT adapter, gl::Caps *caps, + gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions); + +} + +namespace d3d9 +{ + +inline bool isDeviceLostError(HRESULT errorCode) +{ + switch (errorCode) + { + case D3DERR_DRIVERINTERNALERROR: + case D3DERR_DEVICELOST: + case D3DERR_DEVICEHUNG: + case D3DERR_DEVICEREMOVED: + return true; + default: + return false; + } +} + +} + +} + +#endif // LIBGLESV2_RENDERER_RENDERER9_UTILS_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps new file mode 100644 index 0000000000..eb43eb3e7a --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps @@ -0,0 +1,33 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +sampler2D tex : s0; + +uniform float4 mult : c0; +uniform float4 add : c1; + +// Passthrough Pixel Shader +// Outputs texture 0 sampled at texcoord 0. +float4 PS_passthrough(float4 texcoord : TEXCOORD0) : COLOR +{ + return tex2D(tex, texcoord.xy); +}; + +// Luminance Conversion Pixel Shader +// Performs a mad operation using the LA data from the texture with mult.xw and add.xw. +// Returns data in the form of llla +float4 PS_luminance(float4 texcoord : TEXCOORD0) : COLOR +{ + return (tex2D(tex, texcoord.xy).xw * mult.xw + add.xw).xxxy; +}; + +// RGB/A Component Mask Pixel Shader +// Performs a mad operation using the texture's RGBA data with mult.xyzw and add.xyzw. +// Returns data in the form of rgba +float4 PS_componentmask(float4 texcoord : TEXCOORD0) : COLOR +{ + return tex2D(tex, texcoord.xy) * mult + add; +}; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs new file mode 100644 index 0000000000..3bd611ba5d --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs @@ -0,0 +1,43 @@ +// +// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +struct VS_OUTPUT +{ + float4 position : POSITION; + float4 texcoord : TEXCOORD0; +}; + +uniform float4 halfPixelSize : c0; + +// Standard Vertex Shader +// Input 0 is the homogenous position. +// Outputs the homogenous position as-is. +// Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right. +// C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0. +VS_OUTPUT VS_standard(in float4 position : POSITION) +{ + VS_OUTPUT Out; + + Out.position = position + halfPixelSize; + Out.texcoord = position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0); + + return Out; +}; + +// Flip Y Vertex Shader +// Input 0 is the homogenous position. +// Outputs the homogenous position as-is. +// Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right. +// C0.XY must be the half-pixel width and height. C0.ZW must be 0. +VS_OUTPUT VS_flipy(in float4 position : POSITION) +{ + VS_OUTPUT Out; + + Out.position = position + halfPixelSize; + Out.texcoord = position * float4(0.5, 0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0); + + return Out; +}; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp deleted file mode 100644 index 31d5b8b886..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp +++ /dev/null @@ -1,366 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BufferStorage11.cpp Defines the BufferStorage11 class. - -#include "libGLESv2/renderer/d3d11/BufferStorage11.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" - -namespace rx -{ - -BufferStorage11::BufferStorage11(Renderer11 *renderer) -{ - mRenderer = renderer; - - mStagingBuffer = NULL; - mStagingBufferSize = 0; - - mSize = 0; - - mResolvedData = NULL; - mResolvedDataSize = 0; - mResolvedDataValid = false; - - mReadUsageCount = 0; - mWriteUsageCount = 0; -} - -BufferStorage11::~BufferStorage11() -{ - SafeRelease(mStagingBuffer); - - if (mResolvedData) - { - free(mResolvedData); - mResolvedData = NULL; - } - - for (auto it = mDirectBuffers.begin(); it != mDirectBuffers.end(); it++) - { - SafeDelete(it->second); - } -} - -BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage) -{ - ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage)); - return static_cast(bufferStorage); -} - -void *BufferStorage11::getData() -{ - ASSERT(mStagingBuffer); - - if (!mResolvedDataValid) - { - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - HRESULT result; - - if (!mResolvedData || mResolvedDataSize < mStagingBufferSize) - { - free(mResolvedData); - mResolvedData = malloc(mSize); - mResolvedDataSize = mSize; - } - - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource); - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY, (void*)NULL); - } - - memcpy(mResolvedData, mappedResource.pData, mSize); - - context->Unmap(mStagingBuffer, 0); - - mResolvedDataValid = true; - } - - mReadUsageCount = 0; - - return mResolvedData; -} - -void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset) -{ - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - HRESULT result; - - const unsigned int requiredStagingBufferSize = size + offset; - const bool createStagingBuffer = !mStagingBuffer || mStagingBufferSize < requiredStagingBufferSize; - - if (createStagingBuffer) - { - D3D11_BUFFER_DESC bufferDesc; - bufferDesc.ByteWidth = requiredStagingBufferSize; - bufferDesc.Usage = D3D11_USAGE_STAGING; - bufferDesc.BindFlags = 0; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - bufferDesc.MiscFlags = 0; - bufferDesc.StructureByteStride = 0; - - HRESULT result; - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - ID3D11Buffer *newStagingBuffer; - - if (data && offset == 0) - { - D3D11_SUBRESOURCE_DATA initialData; - initialData.pSysMem = data; - initialData.SysMemPitch = requiredStagingBufferSize; - initialData.SysMemSlicePitch = 0; - - result = device->CreateBuffer(&bufferDesc, &initialData, &newStagingBuffer); - } - else - { - result = device->CreateBuffer(&bufferDesc, NULL, &newStagingBuffer); - } - - if (FAILED(result)) - { - mStagingBufferSize = 0; - return gl::error(GL_OUT_OF_MEMORY); - } - - mStagingBufferSize = requiredStagingBufferSize; - - if (mStagingBuffer && offset > 0) - { - // If offset is greater than zero and the buffer is non-null, need to preserve the data from - // the old buffer up to offset - D3D11_BOX srcBox; - srcBox.left = 0; - srcBox.right = std::min(offset, requiredStagingBufferSize); - srcBox.top = 0; - srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; - - context->CopySubresourceRegion(newStagingBuffer, 0, 0, 0, 0, mStagingBuffer, 0, &srcBox); - } - - SafeRelease(mStagingBuffer); - mStagingBuffer = newStagingBuffer; - } - - if (data && (offset != 0 || !createStagingBuffer)) - { - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource); - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY); - } - - unsigned char *offsetBufferPointer = reinterpret_cast(mappedResource.pData) + offset; - memcpy(offsetBufferPointer, data, size); - - context->Unmap(mStagingBuffer, 0); - } - - for (auto it = mDirectBuffers.begin(); it != mDirectBuffers.end(); it++) - { - it->second->markDirty(); - } - - mSize = std::max(mSize, requiredStagingBufferSize); - mWriteUsageCount = 0; - - mResolvedDataValid = false; -} - -void BufferStorage11::copyData(BufferStorage* sourceStorage, unsigned int size, - unsigned int sourceOffset, unsigned int destOffset) -{ - BufferStorage11* source = makeBufferStorage11(sourceStorage); - if (source) - { - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - D3D11_BOX srcBox; - srcBox.left = sourceOffset; - srcBox.right = sourceOffset + size; - srcBox.top = 0; - srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; - - ASSERT(mStagingBuffer && source->mStagingBuffer); - context->CopySubresourceRegion(mStagingBuffer, 0, destOffset, 0, 0, source->mStagingBuffer, 0, &srcBox); - } -} - -void BufferStorage11::clear() -{ - mResolvedDataValid = false; - mSize = 0; -} - -unsigned int BufferStorage11::getSize() const -{ - return mSize; -} - -bool BufferStorage11::supportsDirectBinding() const -{ - return true; -} - -void BufferStorage11::markBufferUsage() -{ - mReadUsageCount++; - mWriteUsageCount++; - - const unsigned int usageLimit = 5; - - if (mReadUsageCount > usageLimit && mResolvedData) - { - free(mResolvedData); - mResolvedData = NULL; - mResolvedDataSize = 0; - mResolvedDataValid = false; - } -} - -ID3D11Buffer *BufferStorage11::getBuffer(BufferUsage usage) -{ - markBufferUsage(); - - DirectBufferStorage11 *directBuffer = NULL; - - auto directBufferIt = mDirectBuffers.find(usage); - if (directBufferIt != mDirectBuffers.end()) - { - directBuffer = directBufferIt->second; - } - - if (directBuffer) - { - if (directBuffer->isDirty()) - { - // if updateFromStagingBuffer returns true, the D3D buffer has been recreated - // and we should update our serial - if (directBuffer->updateFromStagingBuffer(mStagingBuffer, mSize, 0)) - { - updateSerial(); - } - } - } - else - { - // buffer is not allocated, create it - directBuffer = new DirectBufferStorage11(mRenderer, usage); - directBuffer->updateFromStagingBuffer(mStagingBuffer, mSize, 0); - - mDirectBuffers.insert(std::make_pair(usage, directBuffer)); - updateSerial(); - } - - return directBuffer->getD3DBuffer(); -} - -DirectBufferStorage11::DirectBufferStorage11(Renderer11 *renderer, BufferUsage usage) - : mRenderer(renderer), - mUsage(usage), - mDirectBuffer(NULL), - mBufferSize(0), - mDirty(false) -{ -} - -DirectBufferStorage11::~DirectBufferStorage11() -{ - SafeRelease(mDirectBuffer); -} - -BufferUsage DirectBufferStorage11::getUsage() const -{ - return mUsage; -} - -// Returns true if it recreates the direct buffer -bool DirectBufferStorage11::updateFromStagingBuffer(ID3D11Buffer *stagingBuffer, size_t size, size_t offset) -{ - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - // unused for now - ASSERT(offset == 0); - - unsigned int requiredBufferSize = size + offset; - bool createBuffer = !mDirectBuffer || mBufferSize < requiredBufferSize; - - // (Re)initialize D3D buffer if needed - if (createBuffer) - { - D3D11_BUFFER_DESC bufferDesc; - fillBufferDesc(&bufferDesc, mRenderer, mUsage, requiredBufferSize); - - ID3D11Buffer *newBuffer; - HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer); - - if (FAILED(result)) - { - return gl::error(GL_OUT_OF_MEMORY, false); - } - - // No longer need the old buffer - SafeRelease(mDirectBuffer); - mDirectBuffer = newBuffer; - - mBufferSize = bufferDesc.ByteWidth; - } - - // Copy data via staging buffer - D3D11_BOX srcBox; - srcBox.left = 0; - srcBox.right = size; - srcBox.top = 0; - srcBox.bottom = 1; - srcBox.front = 0; - srcBox.back = 1; - - context->CopySubresourceRegion(mDirectBuffer, 0, offset, 0, 0, stagingBuffer, 0, &srcBox); - - mDirty = false; - - return createBuffer; -} - -void DirectBufferStorage11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize) -{ - bufferDesc->ByteWidth = bufferSize; - bufferDesc->MiscFlags = 0; - bufferDesc->StructureByteStride = 0; - - switch (usage) - { - case BUFFER_USAGE_VERTEX: - bufferDesc->Usage = D3D11_USAGE_DEFAULT; - bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER; - bufferDesc->CPUAccessFlags = 0; - break; - - case BUFFER_USAGE_INDEX: - bufferDesc->Usage = D3D11_USAGE_DEFAULT; - bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc->CPUAccessFlags = 0; - break; - - default: - UNREACHABLE(); - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h deleted file mode 100644 index a6afafe1b4..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.h +++ /dev/null @@ -1,92 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BufferStorage11.h Defines the BufferStorage11 class. - -#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ -#define LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ - -#include "libGLESv2/renderer/BufferStorage.h" - -namespace rx -{ -class Renderer; -class Renderer11; -class DirectBufferStorage11; - -enum BufferUsage -{ - BUFFER_USAGE_VERTEX, - BUFFER_USAGE_INDEX, -}; - -class BufferStorage11 : public BufferStorage -{ - public: - explicit BufferStorage11(Renderer11 *renderer); - virtual ~BufferStorage11(); - - static BufferStorage11 *makeBufferStorage11(BufferStorage *bufferStorage); - - virtual void *getData(); - virtual void setData(const void* data, unsigned int size, unsigned int offset); - virtual void copyData(BufferStorage* sourceStorage, unsigned int size, - unsigned int sourceOffset, unsigned int destOffset); - virtual void clear(); - virtual unsigned int getSize() const; - virtual bool supportsDirectBinding() const; - - ID3D11Buffer *getBuffer(BufferUsage usage); - - private: - Renderer11 *mRenderer; - - ID3D11Buffer *mStagingBuffer; - unsigned int mStagingBufferSize; - - std::map mDirectBuffers; - - unsigned int mSize; - - void *mResolvedData; - unsigned int mResolvedDataSize; - bool mResolvedDataValid; - - unsigned int mReadUsageCount; - unsigned int mWriteUsageCount; - - void markBufferUsage(); -}; - -// Each instance of BufferStorageD3DBuffer11 is specialized for a class of D3D binding points -// - vertex buffers -// - index buffers -class DirectBufferStorage11 -{ - public: - DirectBufferStorage11(Renderer11 *renderer, BufferUsage usage); - ~DirectBufferStorage11(); - - BufferUsage getUsage() const; - bool updateFromStagingBuffer(ID3D11Buffer *stagingBuffer, size_t size, size_t offset); - - ID3D11Buffer *getD3DBuffer() { return mDirectBuffer; } - bool isDirty() const { return mDirty; } - void markDirty() { mDirty = true; } - - private: - Renderer11 *mRenderer; - const BufferUsage mUsage; - ID3D11Buffer *mDirectBuffer; - size_t mBufferSize; - bool mDirty; - - static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize); -}; - -} - -#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp deleted file mode 100644 index 2a7d4d43ef..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Fence11.cpp: Defines the rx::Fence11 class which implements rx::FenceImpl. - -#include "libGLESv2/renderer/d3d11/Fence11.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" - -namespace rx -{ - -Fence11::Fence11(rx::Renderer11 *renderer) -{ - mRenderer = renderer; - mQuery = NULL; -} - -Fence11::~Fence11() -{ - if (mQuery) - { - mQuery->Release(); - mQuery = NULL; - } -} - -GLboolean Fence11::isFence() -{ - // GL_NV_fence spec: - // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. - return mQuery != NULL; -} - -void Fence11::setFence(GLenum condition) -{ - if (!mQuery) - { - D3D11_QUERY_DESC queryDesc; - queryDesc.Query = D3D11_QUERY_EVENT; - queryDesc.MiscFlags = 0; - - if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) - { - return gl::error(GL_OUT_OF_MEMORY); - } - } - - mRenderer->getDeviceContext()->End(mQuery); - - setCondition(condition); - setStatus(GL_FALSE); -} - -GLboolean Fence11::testFence() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION, GL_TRUE); - } - - HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, 0); - - if (mRenderer->isDeviceLost()) - { - return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); - } - - ASSERT(result == S_OK || result == S_FALSE); - setStatus(result == S_OK); - return getStatus(); -} - -void Fence11::finishFence() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - while (!testFence()) - { - Sleep(0); - } -} - -void Fence11::getFenceiv(GLenum pname, GLint *params) -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (pname) - { - case GL_FENCE_STATUS_NV: - { - // GL_NV_fence spec: - // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV - // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. - if (getStatus()) - { - params[0] = GL_TRUE; - return; - } - - HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); - - if (mRenderer->isDeviceLost()) - { - params[0] = GL_TRUE; - return gl::error(GL_OUT_OF_MEMORY); - } - - ASSERT(result == S_OK || result == S_FALSE); - setStatus(result == S_OK); - params[0] = getStatus(); - - break; - } - case GL_FENCE_CONDITION_NV: - params[0] = getCondition(); - break; - default: - return gl::error(GL_INVALID_ENUM); - break; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.h deleted file mode 100644 index a5398bca14..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Fence11.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Fence11.h: Defines the rx::Fence11 class which implements rx::FenceImpl. - -#ifndef LIBGLESV2_RENDERER_Fence11_H_ -#define LIBGLESV2_RENDERER_Fence11_H_ - -#include "libGLESv2/renderer/FenceImpl.h" - -namespace rx -{ -class Renderer11; - -class Fence11 : public FenceImpl -{ - public: - explicit Fence11(rx::Renderer11 *renderer); - virtual ~Fence11(); - - GLboolean isFence(); - void setFence(GLenum condition); - GLboolean testFence(); - void finishFence(); - void getFenceiv(GLenum pname, GLint *params); - - private: - DISALLOW_COPY_AND_ASSIGN(Fence11); - - rx::Renderer11 *mRenderer; - ID3D11Query *mQuery; -}; - -} - -#endif // LIBGLESV2_RENDERER_FENCE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp deleted file mode 100644 index 5d039a35e8..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.cpp +++ /dev/null @@ -1,498 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Image11.h: Implements the rx::Image11 class, which acts as the interface to -// the actual underlying resources of a Texture - -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/Image11.h" -#include "libGLESv2/renderer/d3d11/TextureStorage11.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" - -#include "libGLESv2/main.h" -#include "libGLESv2/utilities.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/generatemip.h" - -namespace rx -{ - -Image11::Image11() -{ - mStagingTexture = NULL; - mRenderer = NULL; - mDXGIFormat = DXGI_FORMAT_UNKNOWN; -} - -Image11::~Image11() -{ - if (mStagingTexture) - { - mStagingTexture->Release(); - } -} - -Image11 *Image11::makeImage11(Image *img) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::Image11*, img)); - return static_cast(img); -} - -void Image11::generateMipmap(Image11 *dest, Image11 *src) -{ - ASSERT(src->getDXGIFormat() == dest->getDXGIFormat()); - ASSERT(src->getWidth() == 1 || src->getWidth() / 2 == dest->getWidth()); - ASSERT(src->getHeight() == 1 || src->getHeight() / 2 == dest->getHeight()); - - D3D11_MAPPED_SUBRESOURCE destMapped, srcMapped; - dest->map(D3D11_MAP_WRITE, &destMapped); - src->map(D3D11_MAP_READ, &srcMapped); - - const unsigned char *sourceData = reinterpret_cast(srcMapped.pData); - unsigned char *destData = reinterpret_cast(destMapped.pData); - - if (sourceData && destData) - { - switch (src->getDXGIFormat()) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - case DXGI_FORMAT_B8G8R8A8_UNORM: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_A8_UNORM: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R8_UNORM: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R32G32B32A32_FLOAT: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R32G32B32_FLOAT: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R16G16B16A16_FLOAT: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R8G8_UNORM: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R16_FLOAT: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R16G16_FLOAT: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R32_FLOAT: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - case DXGI_FORMAT_R32G32_FLOAT: - GenerateMip(src->getWidth(), src->getHeight(), sourceData, srcMapped.RowPitch, destData, destMapped.RowPitch); - break; - default: - UNREACHABLE(); - break; - } - - dest->unmap(); - src->unmap(); - } - - dest->markDirty(); -} - -static bool FormatRequiresInitialization(DXGI_FORMAT dxgiFormat, GLenum internalFormat) -{ - return (dxgiFormat == DXGI_FORMAT_R8G8B8A8_UNORM && gl::GetAlphaSize(internalFormat) == 0) || - (dxgiFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && gl::GetAlphaSize(internalFormat) == 0); -} - -bool Image11::isDirty() const -{ - return ((mStagingTexture || FormatRequiresInitialization(mDXGIFormat, mInternalFormat)) && mDirty); -} - -bool Image11::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); - return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, 0, xoffset, yoffset, width, height); -} - -bool Image11::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); - return storage11->updateSubresourceLevel(getStagingTexture(), getStagingSubresource(), level, face, xoffset, yoffset, width, height); -} - -bool Image11::redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) -{ - if (mWidth != width || - mHeight != height || - mInternalFormat != internalformat || - forceRelease) - { - mRenderer = Renderer11::makeRenderer11(renderer); - - mWidth = width; - mHeight = height; - mInternalFormat = internalformat; - // compute the d3d format that will be used - mDXGIFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel()); - mActualFormat = d3d11_gl::ConvertTextureInternalFormat(mDXGIFormat); - - if (mStagingTexture) - { - mStagingTexture->Release(); - mStagingTexture = NULL; - } - - return true; - } - - return false; -} - -bool Image11::isRenderableFormat() const -{ - return TextureStorage11::IsTextureFormatRenderable(mDXGIFormat); -} - -DXGI_FORMAT Image11::getDXGIFormat() const -{ - // this should only happen if the image hasn't been redefined first - // which would be a bug by the caller - ASSERT(mDXGIFormat != DXGI_FORMAT_UNKNOWN); - - return mDXGIFormat; -} - -// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input -// into the target pixel rectangle. -void Image11::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input) -{ - D3D11_MAPPED_SUBRESOURCE mappedImage; - HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); - if (FAILED(result)) - { - ERR("Could not map image for loading."); - return; - } - - GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment); - size_t pixelSize = d3d11::ComputePixelSizeBits(mDXGIFormat) / 8; - void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + (yoffset * mappedImage.RowPitch + xoffset * pixelSize)); - - switch (mInternalFormat) - { - case GL_ALPHA8_EXT: - if (mRenderer->getFeatureLevel() >= D3D_FEATURE_LEVEL_10_0) - loadAlphaDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - else - loadAlphaDataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_LUMINANCE8_EXT: - loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false); - break; - case GL_ALPHA32F_EXT: - loadAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_LUMINANCE32F_EXT: - loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_ALPHA16F_EXT: - loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_LUMINANCE16F_EXT: - loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_LUMINANCE8_ALPHA8_EXT: - loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData, false); - break; - case GL_LUMINANCE_ALPHA32F_EXT: - loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_LUMINANCE_ALPHA16F_EXT: - loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGB8_OES: - loadRGBUByteDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGB565: - loadRGB565DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGBA8_OES: - loadRGBAUByteDataToNative(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGBA4: - loadRGBA4444DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGB5_A1: - loadRGBA5551DataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_BGRA8_EXT: - loadBGRADataToBGRA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGB32F_EXT: - loadRGBFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGB16F_EXT: - loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGBA32F_EXT: - loadRGBAFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - case GL_RGBA16F_EXT: - loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, mappedImage.RowPitch, offsetMappedData); - break; - default: UNREACHABLE(); - } - - unmap(); -} - -void Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - const void *input) -{ - ASSERT(xoffset % 4 == 0); - ASSERT(yoffset % 4 == 0); - - D3D11_MAPPED_SUBRESOURCE mappedImage; - HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); - if (FAILED(result)) - { - ERR("Could not map image for loading."); - return; - } - - // Size computation assumes a 4x4 block compressed texture format - size_t blockSize = d3d11::ComputeBlockSizeBits(mDXGIFormat) / 8; - void* offsetMappedData = (void*)((BYTE *)mappedImage.pData + ((yoffset / 4) * mappedImage.RowPitch + (xoffset / 4) * blockSize)); - - GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat); - GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat); - int rows = inputSize / inputPitch; - for (int i = 0; i < rows; ++i) - { - memcpy((void*)((BYTE*)offsetMappedData + i * mappedImage.RowPitch), (void*)((BYTE*)input + i * inputPitch), inputPitch); - } - - unmap(); -} - -void Image11::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) -{ - gl::Renderbuffer *colorbuffer = source->getReadColorbuffer(); - - if (colorbuffer && colorbuffer->getActualFormat() == (GLuint)mActualFormat) - { - // No conversion needed-- use copyback fastpath - ID3D11Texture2D *colorBufferTexture = NULL; - unsigned int subresourceIndex = 0; - - if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) - { - D3D11_TEXTURE2D_DESC textureDesc; - colorBufferTexture->GetDesc(&textureDesc); - - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - ID3D11Texture2D* srcTex = NULL; - if (textureDesc.SampleDesc.Count > 1) - { - D3D11_TEXTURE2D_DESC resolveDesc; - resolveDesc.Width = textureDesc.Width; - resolveDesc.Height = textureDesc.Height; - resolveDesc.MipLevels = 1; - resolveDesc.ArraySize = 1; - resolveDesc.Format = textureDesc.Format; - resolveDesc.SampleDesc.Count = 1; - resolveDesc.SampleDesc.Quality = 0; - resolveDesc.Usage = D3D11_USAGE_DEFAULT; - resolveDesc.BindFlags = 0; - resolveDesc.CPUAccessFlags = 0; - resolveDesc.MiscFlags = 0; - - HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex); - if (FAILED(result)) - { - ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result); - return; - } - - deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format); - subresourceIndex = 0; - } - else - { - srcTex = colorBufferTexture; - srcTex->AddRef(); - } - - D3D11_BOX srcBox; - srcBox.left = x; - srcBox.right = x + width; - srcBox.top = y; - srcBox.bottom = y + height; - srcBox.front = 0; - srcBox.back = 1; - - deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, 0, srcTex, subresourceIndex, &srcBox); - - srcTex->Release(); - colorBufferTexture->Release(); - } - } - else - { - // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels - D3D11_MAPPED_SUBRESOURCE mappedImage; - HRESULT result = map(D3D11_MAP_WRITE, &mappedImage); - - // determine the offset coordinate into the destination buffer - GLsizei rowOffset = gl::ComputePixelSize(mActualFormat) * xoffset; - void *dataOffset = static_cast(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset; - - mRenderer->readPixels(source, x, y, width, height, gl::ExtractFormat(mInternalFormat), - gl::ExtractType(mInternalFormat), mappedImage.RowPitch, false, 4, dataOffset); - - unmap(); - } -} - -ID3D11Texture2D *Image11::getStagingTexture() -{ - createStagingTexture(); - - return mStagingTexture; -} - -unsigned int Image11::getStagingSubresource() -{ - createStagingTexture(); - - return mStagingSubresource; -} - -template -static void setDefaultData(ID3D11DeviceContext *deviceContext, ID3D11Texture2D *texture, UINT subresource, - GLsizei width, GLsizei height, const T (&defaultData)[N]) -{ - D3D11_MAPPED_SUBRESOURCE map; - deviceContext->Map(texture, subresource, D3D11_MAP_WRITE, 0, &map); - - unsigned char* ptr = reinterpret_cast(map.pData); - size_t pixelSize = sizeof(T) * N; - - for (GLsizei y = 0; y < height; y++) - { - for (GLsizei x = 0; x < width; x++) - { - memcpy(ptr + (y * map.RowPitch) + (x * pixelSize), defaultData, pixelSize); - } - } - - deviceContext->Unmap(texture, subresource); -} - -void Image11::createStagingTexture() -{ - if (mStagingTexture) - { - return; - } - - ID3D11Texture2D *newTexture = NULL; - int lodOffset = 1; - const DXGI_FORMAT dxgiFormat = getDXGIFormat(); - ASSERT(!d3d11::IsDepthStencilFormat(dxgiFormat)); // We should never get here for depth textures - - if (mWidth != 0 && mHeight != 0) - { - GLsizei width = mWidth; - GLsizei height = mHeight; - - // adjust size if needed for compressed textures - gl::MakeValidSize(false, d3d11::IsCompressed(dxgiFormat), &width, &height, &lodOffset); - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = width; - desc.Height = height; - desc.MipLevels = lodOffset + 1; - desc.ArraySize = 1; - desc.Format = dxgiFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_STAGING; - desc.BindFlags = 0; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - - HRESULT result = device->CreateTexture2D(&desc, NULL, &newTexture); - - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - ERR("Creating image failed."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - - mStagingTexture = newTexture; - mStagingSubresource = D3D11CalcSubresource(lodOffset, 0, lodOffset + 1); - mDirty = false; - - if (mDXGIFormat == DXGI_FORMAT_R8G8B8A8_UNORM && gl::GetAlphaSize(mInternalFormat) == 0) - { - unsigned char defaultPixel[4] = { 0, 0, 0, 255 }; - setDefaultData(mRenderer->getDeviceContext(), mStagingTexture, mStagingSubresource, mWidth, mHeight, defaultPixel); - } - else if (mDXGIFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && gl::GetAlphaSize(mInternalFormat) == 0) - { - float defaultPixel[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; - setDefaultData(mRenderer->getDeviceContext(), mStagingTexture, mStagingSubresource, mWidth, mHeight, defaultPixel); - } -} - -HRESULT Image11::map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map) -{ - createStagingTexture(); - - HRESULT result = E_FAIL; - - if (mStagingTexture) - { - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - result = deviceContext->Map(mStagingTexture, mStagingSubresource, mapType, 0, map); - - // this can fail if the device is removed (from TDR) - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - } - else if (SUCCEEDED(result)) - { - mDirty = true; - } - } - - return result; -} - -void Image11::unmap() -{ - if (mStagingTexture) - { - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - deviceContext->Unmap(mStagingTexture, mStagingSubresource); - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.h deleted file mode 100644 index 11a6492dc8..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Image11.h +++ /dev/null @@ -1,76 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Image11.h: Defines the rx::Image11 class, which acts as the interface to -// the actual underlying resources of a Texture - -#ifndef LIBGLESV2_RENDERER_IMAGE11_H_ -#define LIBGLESV2_RENDERER_IMAGE11_H_ - -#include "libGLESv2/renderer/Image.h" - -#include "common/debug.h" - -namespace gl -{ -class Framebuffer; -} - -namespace rx -{ -class Renderer; -class Renderer11; -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; - -class Image11 : public Image -{ - public: - Image11(); - virtual ~Image11(); - - static Image11 *makeImage11(Image *img); - - static void generateMipmap(Image11 *dest, Image11 *src); - - virtual bool isDirty() const; - - virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - - virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease); - - virtual bool isRenderableFormat() const; - DXGI_FORMAT getDXGIFormat() const; - - virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input); - virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - const void *input); - - virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - - protected: - HRESULT map(D3D11_MAP mapType, D3D11_MAPPED_SUBRESOURCE *map); - void unmap(); - - private: - DISALLOW_COPY_AND_ASSIGN(Image11); - - ID3D11Texture2D *getStagingTexture(); - unsigned int getStagingSubresource(); - void createStagingTexture(); - - Renderer11 *mRenderer; - - DXGI_FORMAT mDXGIFormat; - ID3D11Texture2D *mStagingTexture; - unsigned int mStagingSubresource; -}; - -} - -#endif // LIBGLESV2_RENDERER_IMAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp deleted file mode 100644 index 44f9976d43..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.cpp +++ /dev/null @@ -1,183 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation. - -#include "libGLESv2/renderer/d3d11/IndexBuffer11.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" - -namespace rx -{ - -IndexBuffer11::IndexBuffer11(Renderer11 *const renderer) : mRenderer(renderer) -{ - mBuffer = NULL; - mBufferSize = 0; - mDynamicUsage = false; -} - -IndexBuffer11::~IndexBuffer11() -{ - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - } -} - -bool IndexBuffer11::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) -{ - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - } - - updateSerial(); - - if (bufferSize > 0) - { - ID3D11Device* dxDevice = mRenderer->getDevice(); - - D3D11_BUFFER_DESC bufferDesc; - bufferDesc.ByteWidth = bufferSize; - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - bufferDesc.MiscFlags = 0; - bufferDesc.StructureByteStride = 0; - - HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); - if (FAILED(result)) - { - return false; - } - } - - mBufferSize = bufferSize; - mIndexType = indexType; - mDynamicUsage = dynamic; - - return true; -} - -IndexBuffer11 *IndexBuffer11::makeIndexBuffer11(IndexBuffer *indexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer11*, indexBuffer)); - return static_cast(indexBuffer); -} - -bool IndexBuffer11::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) -{ - if (mBuffer) - { - // Check for integer overflows and out-out-bounds map requests - if (offset + size < offset || offset + size > mBufferSize) - { - ERR("Index buffer map range is not inside the buffer."); - return false; - } - - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Index buffer map failed with error 0x%08x", result); - return false; - } - - *outMappedMemory = reinterpret_cast(mappedResource.pData) + offset; - return true; - } - else - { - ERR("Index buffer not initialized."); - return false; - } -} - -bool IndexBuffer11::unmapBuffer() -{ - if (mBuffer) - { - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - dxContext->Unmap(mBuffer, 0); - return true; - } - else - { - ERR("Index buffer not initialized."); - return false; - } -} - -GLenum IndexBuffer11::getIndexType() const -{ - return mIndexType; -} - -unsigned int IndexBuffer11::getBufferSize() const -{ - return mBufferSize; -} - -bool IndexBuffer11::setSize(unsigned int bufferSize, GLenum indexType) -{ - if (bufferSize > mBufferSize || indexType != mIndexType) - { - return initialize(bufferSize, indexType, mDynamicUsage); - } - else - { - return true; - } -} - -bool IndexBuffer11::discard() -{ - if (mBuffer) - { - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Index buffer map failed with error 0x%08x", result); - return false; - } - - dxContext->Unmap(mBuffer, 0); - - return true; - } - else - { - ERR("Index buffer not initialized."); - return false; - } -} - -DXGI_FORMAT IndexBuffer11::getIndexFormat() const -{ - switch (mIndexType) - { - case GL_UNSIGNED_BYTE: return DXGI_FORMAT_R16_UINT; - case GL_UNSIGNED_SHORT: return DXGI_FORMAT_R16_UINT; - case GL_UNSIGNED_INT: return DXGI_FORMAT_R32_UINT; - default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; - } -} - -ID3D11Buffer *IndexBuffer11::getBuffer() const -{ - return mBuffer; -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h deleted file mode 100644 index 39a61946ad..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/IndexBuffer11.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// IndexBuffer11.h: Defines the D3D11 IndexBuffer implementation. - -#ifndef LIBGLESV2_RENDERER_INDEXBUFFER11_H_ -#define LIBGLESV2_RENDERER_INDEXBUFFER11_H_ - -#include "libGLESv2/renderer/IndexBuffer.h" - -namespace rx -{ -class Renderer11; - -class IndexBuffer11 : public IndexBuffer -{ - public: - explicit IndexBuffer11(Renderer11 *const renderer); - virtual ~IndexBuffer11(); - - virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); - - static IndexBuffer11 *makeIndexBuffer11(IndexBuffer *indexBuffer); - - virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); - virtual bool unmapBuffer(); - - virtual GLenum getIndexType() const; - virtual unsigned int getBufferSize() const; - virtual bool setSize(unsigned int bufferSize, GLenum indexType); - - virtual bool discard(); - - DXGI_FORMAT getIndexFormat() const; - ID3D11Buffer *getBuffer() const; - - private: - DISALLOW_COPY_AND_ASSIGN(IndexBuffer11); - - rx::Renderer11 *const mRenderer; - - ID3D11Buffer *mBuffer; - unsigned int mBufferSize; - GLenum mIndexType; - bool mDynamicUsage; -}; - -} - -#endif // LIBGLESV2_RENDERER_INDEXBUFFER11_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp deleted file mode 100644 index 4940b8c638..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.cpp +++ /dev/null @@ -1,213 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches -// D3D11 input layouts. - -#include "libGLESv2/renderer/d3d11/InputLayoutCache.h" -#include "libGLESv2/renderer/d3d11/VertexBuffer11.h" -#include "libGLESv2/renderer/d3d11/BufferStorage11.h" -#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/renderer/VertexDataManager.h" - -#include "third_party/murmurhash/MurmurHash3.h" - -namespace rx -{ - -const unsigned int InputLayoutCache::kMaxInputLayouts = 1024; - -InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts) -{ - mCounter = 0; - mDevice = NULL; - mDeviceContext = NULL; - mCurrentIL = NULL; - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentBuffers[i] = -1; - mCurrentVertexStrides[i] = -1; - mCurrentVertexOffsets[i] = -1; - } -} - -InputLayoutCache::~InputLayoutCache() -{ - clear(); -} - -void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context) -{ - clear(); - mDevice = device; - mDeviceContext = context; -} - -void InputLayoutCache::clear() -{ - for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) - { - i->second.inputLayout->Release(); - } - mInputLayoutMap.clear(); - markDirty(); -} - -void InputLayoutCache::markDirty() -{ - mCurrentIL = NULL; - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mCurrentBuffers[i] = -1; - mCurrentVertexStrides[i] = -1; - mCurrentVertexOffsets[i] = -1; - } -} - -GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], - gl::ProgramBinary *programBinary) -{ - int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]; - programBinary->sortAttributesByLayout(attributes, sortedSemanticIndices); - - if (!mDevice || !mDeviceContext) - { - ERR("InputLayoutCache is not initialized."); - return GL_INVALID_OPERATION; - } - - InputLayoutKey ilKey = { 0 }; - - ID3D11Buffer *vertexBuffers[gl::MAX_VERTEX_ATTRIBS] = { NULL }; - unsigned int vertexBufferSerials[gl::MAX_VERTEX_ATTRIBS] = { 0 }; - UINT vertexStrides[gl::MAX_VERTEX_ATTRIBS] = { 0 }; - UINT vertexOffsets[gl::MAX_VERTEX_ATTRIBS] = { 0 }; - - static const char* semanticName = "TEXCOORD"; - - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - if (attributes[i].active) - { - VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer); - BufferStorage11 *bufferStorage = attributes[i].storage ? BufferStorage11::makeBufferStorage11(attributes[i].storage) : NULL; - - D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; - - // Record the type of the associated vertex shader vector in our key - // This will prevent mismatched vertex shaders from using the same input layout - GLint attributeSize; - programBinary->getActiveAttribute(sortedSemanticIndices[i], 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL); - - ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName; - ilKey.elements[ilKey.elementCount].desc.SemanticIndex = i; - ilKey.elements[ilKey.elementCount].desc.Format = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDXGIFormat(*attributes[i].attribute) : DXGI_FORMAT_R32G32B32A32_FLOAT; - ilKey.elements[ilKey.elementCount].desc.InputSlot = i; - ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0; - ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass; - ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = attributes[i].divisor; - ilKey.elementCount++; - - vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX) : vertexBuffer->getBuffer(); - vertexBufferSerials[i] = bufferStorage ? bufferStorage->getSerial() : vertexBuffer->getSerial(); - vertexStrides[i] = attributes[i].stride; - vertexOffsets[i] = attributes[i].offset; - } - } - - ID3D11InputLayout *inputLayout = NULL; - - InputLayoutMap::iterator i = mInputLayoutMap.find(ilKey); - if (i != mInputLayoutMap.end()) - { - inputLayout = i->second.inputLayout; - i->second.lastUsedTime = mCounter++; - } - else - { - ShaderExecutable11 *shader = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable()); - - D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS]; - for (unsigned int j = 0; j < ilKey.elementCount; ++j) - { - descs[j] = ilKey.elements[j].desc; - } - - HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader->getFunction(), shader->getLength(), &inputLayout); - if (FAILED(result)) - { - ERR("Failed to crate input layout, result: 0x%08x", result); - return GL_INVALID_OPERATION; - } - - if (mInputLayoutMap.size() >= kMaxInputLayouts) - { - TRACE("Overflowed the limit of %u input layouts, removing the least recently used " - "to make room.", kMaxInputLayouts); - - InputLayoutMap::iterator leastRecentlyUsed = mInputLayoutMap.begin(); - for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++) - { - if (i->second.lastUsedTime < leastRecentlyUsed->second.lastUsedTime) - { - leastRecentlyUsed = i; - } - } - leastRecentlyUsed->second.inputLayout->Release(); - mInputLayoutMap.erase(leastRecentlyUsed); - } - - InputLayoutCounterPair inputCounterPair; - inputCounterPair.inputLayout = inputLayout; - inputCounterPair.lastUsedTime = mCounter++; - - mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair)); - } - - if (inputLayout != mCurrentIL) - { - mDeviceContext->IASetInputLayout(inputLayout); - mCurrentIL = inputLayout; - } - - for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - if (vertexBufferSerials[i] != mCurrentBuffers[i] || vertexStrides[i] != mCurrentVertexStrides[i] || - vertexOffsets[i] != mCurrentVertexOffsets[i]) - { - mDeviceContext->IASetVertexBuffers(i, 1, &vertexBuffers[i], &vertexStrides[i], &vertexOffsets[i]); - mCurrentBuffers[i] = vertexBufferSerials[i]; - mCurrentVertexStrides[i] = vertexStrides[i]; - mCurrentVertexOffsets[i] = vertexOffsets[i]; - } - } - - return GL_NO_ERROR; -} - -std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout) -{ - static const unsigned int seed = 0xDEADBEEF; - - std::size_t hash = 0; - MurmurHash3_x86_32(inputLayout.begin(), inputLayout.end() - inputLayout.begin(), seed, &hash); - return hash; -} - -bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b) -{ - if (a.elementCount != b.elementCount) - { - return false; - } - - return std::equal(a.begin(), a.end(), b.begin()); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h deleted file mode 100644 index bb1a8eebcf..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/InputLayoutCache.h +++ /dev/null @@ -1,95 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// InputLayoutCache.h: Defines InputLayoutCache, a class that builds and caches -// D3D11 input layouts. - -#ifndef LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ -#define LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ - -#include "libGLESv2/Constants.h" -#include "common/angleutils.h" - -namespace gl -{ -class ProgramBinary; -} - -namespace rx -{ -struct TranslatedAttribute; - -class InputLayoutCache -{ - public: - InputLayoutCache(); - virtual ~InputLayoutCache(); - - void initialize(ID3D11Device *device, ID3D11DeviceContext *context); - void clear(); - void markDirty(); - - GLenum applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS], - gl::ProgramBinary *programBinary); - - private: - DISALLOW_COPY_AND_ASSIGN(InputLayoutCache); - - struct InputLayoutElement - { - D3D11_INPUT_ELEMENT_DESC desc; - GLenum glslElementType; - }; - - struct InputLayoutKey - { - unsigned int elementCount; - InputLayoutElement elements[gl::MAX_VERTEX_ATTRIBS]; - - const char *begin() const - { - return reinterpret_cast(&elementCount); - } - - const char *end() const - { - return reinterpret_cast(&elements[elementCount]); - } - }; - - struct InputLayoutCounterPair - { - ID3D11InputLayout *inputLayout; - unsigned long long lastUsedTime; - }; - - ID3D11InputLayout *mCurrentIL; - unsigned int mCurrentBuffers[gl::MAX_VERTEX_ATTRIBS]; - UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS]; - UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS]; - - static std::size_t hashInputLayout(const InputLayoutKey &inputLayout); - static bool compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b); - - typedef std::size_t (*InputLayoutHashFunction)(const InputLayoutKey &); - typedef bool (*InputLayoutEqualityFunction)(const InputLayoutKey &, const InputLayoutKey &); - typedef std::unordered_map InputLayoutMap; - InputLayoutMap mInputLayoutMap; - - static const unsigned int kMaxInputLayouts; - - unsigned long long mCounter; - - ID3D11Device *mDevice; - ID3D11DeviceContext *mDeviceContext; -}; - -} - -#endif // LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp deleted file mode 100644 index 24c0330a1e..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.cpp +++ /dev/null @@ -1,122 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl. - -#include "libGLESv2/renderer/d3d11/Query11.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -Query11::Query11(rx::Renderer11 *renderer, GLenum type) : QueryImpl(type) -{ - mRenderer = renderer; - mQuery = NULL; -} - -Query11::~Query11() -{ - if (mQuery) - { - mQuery->Release(); - mQuery = NULL; - } -} - -void Query11::begin() -{ - if (mQuery == NULL) - { - D3D11_QUERY_DESC queryDesc; - queryDesc.Query = D3D11_QUERY_OCCLUSION; - queryDesc.MiscFlags = 0; - - if (FAILED(mRenderer->getDevice()->CreateQuery(&queryDesc, &mQuery))) - { - return gl::error(GL_OUT_OF_MEMORY); - } - } - - mRenderer->getDeviceContext()->Begin(mQuery); -} - -void Query11::end() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - mRenderer->getDeviceContext()->End(mQuery); - - mStatus = GL_FALSE; - mResult = GL_FALSE; -} - -GLuint Query11::getResult() -{ - if (mQuery != NULL) - { - while (!testQuery()) - { - Sleep(0); - // explicitly check for device loss, some drivers seem to return S_FALSE - // if the device is lost - if (mRenderer->testDeviceLost(true)) - { - return gl::error(GL_OUT_OF_MEMORY, 0); - } - } - } - - return mResult; -} - -GLboolean Query11::isResultAvailable() -{ - if (mQuery != NULL) - { - testQuery(); - } - - return mStatus; -} - -GLboolean Query11::testQuery() -{ - if (mQuery != NULL && mStatus != GL_TRUE) - { - UINT64 numPixels = 0; - HRESULT result = mRenderer->getDeviceContext()->GetData(mQuery, &numPixels, sizeof(UINT64), 0); - if (result == S_OK) - { - mStatus = GL_TRUE; - - switch (getType()) - { - case GL_ANY_SAMPLES_PASSED_EXT: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: - mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; - break; - default: - UNREACHABLE(); - } - } - else if (mRenderer->testDeviceLost(true)) - { - return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); - } - - return mStatus; - } - - return GL_TRUE; // prevent blocking when query is null -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.h deleted file mode 100644 index 0a03de77ca..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Query11.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Query11.h: Defines the rx::Query11 class which implements rx::QueryImpl. - -#ifndef LIBGLESV2_RENDERER_QUERY11_H_ -#define LIBGLESV2_RENDERER_QUERY11_H_ - -#include "libGLESv2/renderer/QueryImpl.h" - -namespace rx -{ -class Renderer11; - -class Query11 : public QueryImpl -{ - public: - Query11(rx::Renderer11 *renderer, GLenum type); - virtual ~Query11(); - - void begin(); - void end(); - GLuint getResult(); - GLboolean isResultAvailable(); - - private: - DISALLOW_COPY_AND_ASSIGN(Query11); - - GLboolean testQuery(); - - rx::Renderer11 *mRenderer; - ID3D11Query *mQuery; -}; - -} - -#endif // LIBGLESV2_RENDERER_QUERY11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp deleted file mode 100644 index a1c324cd80..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.cpp +++ /dev/null @@ -1,439 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderStateCache.cpp: Defines rx::RenderStateCache, a cache of Direct3D render -// state objects. - -#include "libGLESv2/renderer/d3d11/RenderStateCache.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" - -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/utilities.h" -#include "common/debug.h" -#include "third_party/murmurhash/MurmurHash3.h" - -namespace rx -{ - -// MSDN's documentation of ID3D11Device::CreateBlendState, ID3D11Device::CreateRasterizerState, -// ID3D11Device::CreateDepthStencilState and ID3D11Device::CreateSamplerState claims the maximum -// number of unique states of each type an application can create is 4096 -const unsigned int RenderStateCache::kMaxBlendStates = 4096; -const unsigned int RenderStateCache::kMaxRasterizerStates = 4096; -const unsigned int RenderStateCache::kMaxDepthStencilStates = 4096; -const unsigned int RenderStateCache::kMaxSamplerStates = 4096; - -RenderStateCache::RenderStateCache() : mDevice(NULL), mCounter(0), - mBlendStateCache(kMaxBlendStates, hashBlendState, compareBlendStates), - mRasterizerStateCache(kMaxRasterizerStates, hashRasterizerState, compareRasterizerStates), - mDepthStencilStateCache(kMaxDepthStencilStates, hashDepthStencilState, compareDepthStencilStates), - mSamplerStateCache(kMaxSamplerStates, hashSamplerState, compareSamplerStates) -{ -} - -RenderStateCache::~RenderStateCache() -{ - clear(); -} - -void RenderStateCache::initialize(ID3D11Device *device) -{ - clear(); - mDevice = device; -} - -void RenderStateCache::clear() -{ - for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++) - { - i->second.first->Release(); - } - mBlendStateCache.clear(); - - for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++) - { - i->second.first->Release(); - } - mRasterizerStateCache.clear(); - - for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++) - { - i->second.first->Release(); - } - mDepthStencilStateCache.clear(); - - for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++) - { - i->second.first->Release(); - } - mSamplerStateCache.clear(); -} - -std::size_t RenderStateCache::hashBlendState(const BlendStateKey &blendState) -{ - static const unsigned int seed = 0xABCDEF98; - - std::size_t hash = 0; - MurmurHash3_x86_32(&blendState, sizeof(BlendStateKey), seed, &hash); - return hash; -} - -bool RenderStateCache::compareBlendStates(const BlendStateKey &a, const BlendStateKey &b) -{ - return memcmp(&a, &b, sizeof(gl::BlendState)) == 0; -} - -ID3D11BlendState *RenderStateCache::getBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState) -{ - if (!mDevice) - { - ERR("RenderStateCache is not initialized."); - return NULL; - } - - bool mrt = false; - - BlendStateKey key = { 0 }; - key.blendState = blendState; - for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) - { - gl::Renderbuffer *renderBuffer = framebuffer->getColorbuffer(i); - if (renderBuffer) - { - if (i > 0) - { - mrt = true; - } - - GLenum internalFormat = renderBuffer->getInternalFormat(); - key.rtChannels[i][0] = gl::GetRedSize(internalFormat) > 0; - key.rtChannels[i][1] = gl::GetGreenSize(internalFormat) > 0; - key.rtChannels[i][2] = gl::GetBlueSize(internalFormat) > 0;; - key.rtChannels[i][3] = gl::GetAlphaSize(internalFormat) > 0; - } - else - { - key.rtChannels[i][0] = false; - key.rtChannels[i][1] = false; - key.rtChannels[i][2] = false; - key.rtChannels[i][3] = false; - } - } - - BlendStateMap::iterator i = mBlendStateCache.find(key); - if (i != mBlendStateCache.end()) - { - BlendStateCounterPair &state = i->second; - state.second = mCounter++; - return state.first; - } - else - { - if (mBlendStateCache.size() >= kMaxBlendStates) - { - TRACE("Overflowed the limit of %u blend states, removing the least recently used " - "to make room.", kMaxBlendStates); - - BlendStateMap::iterator leastRecentlyUsed = mBlendStateCache.begin(); - for (BlendStateMap::iterator i = mBlendStateCache.begin(); i != mBlendStateCache.end(); i++) - { - if (i->second.second < leastRecentlyUsed->second.second) - { - leastRecentlyUsed = i; - } - } - leastRecentlyUsed->second.first->Release(); - mBlendStateCache.erase(leastRecentlyUsed); - } - - // Create a new blend state and insert it into the cache - D3D11_BLEND_DESC blendDesc = { 0 }; - blendDesc.AlphaToCoverageEnable = blendState.sampleAlphaToCoverage; - blendDesc.IndependentBlendEnable = mrt ? TRUE : FALSE; - - for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) - { - D3D11_RENDER_TARGET_BLEND_DESC &rtBlend = blendDesc.RenderTarget[i]; - - rtBlend.BlendEnable = blendState.blend; - if (blendState.blend) - { - rtBlend.SrcBlend = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendRGB, false); - rtBlend.DestBlend = gl_d3d11::ConvertBlendFunc(blendState.destBlendRGB, false); - rtBlend.BlendOp = gl_d3d11::ConvertBlendOp(blendState.blendEquationRGB); - - rtBlend.SrcBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.sourceBlendAlpha, true); - rtBlend.DestBlendAlpha = gl_d3d11::ConvertBlendFunc(blendState.destBlendAlpha, true); - rtBlend.BlendOpAlpha = gl_d3d11::ConvertBlendOp(blendState.blendEquationAlpha); - } - - rtBlend.RenderTargetWriteMask = gl_d3d11::ConvertColorMask(key.rtChannels[i][0] && blendState.colorMaskRed, - key.rtChannels[i][1] && blendState.colorMaskGreen, - key.rtChannels[i][2] && blendState.colorMaskBlue, - key.rtChannels[i][3] && blendState.colorMaskAlpha); - } - - ID3D11BlendState *dx11BlendState = NULL; - HRESULT result = mDevice->CreateBlendState(&blendDesc, &dx11BlendState); - if (FAILED(result) || !dx11BlendState) - { - ERR("Unable to create a ID3D11BlendState, HRESULT: 0x%X.", result); - return NULL; - } - - mBlendStateCache.insert(std::make_pair(key, std::make_pair(dx11BlendState, mCounter++))); - - return dx11BlendState; - } -} - -std::size_t RenderStateCache::hashRasterizerState(const RasterizerStateKey &rasterState) -{ - static const unsigned int seed = 0xABCDEF98; - - std::size_t hash = 0; - MurmurHash3_x86_32(&rasterState, sizeof(RasterizerStateKey), seed, &hash); - return hash; -} - -bool RenderStateCache::compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b) -{ - return memcmp(&a, &b, sizeof(RasterizerStateKey)) == 0; -} - -ID3D11RasterizerState *RenderStateCache::getRasterizerState(const gl::RasterizerState &rasterState, - bool scissorEnabled, unsigned int depthSize) -{ - if (!mDevice) - { - ERR("RenderStateCache is not initialized."); - return NULL; - } - - RasterizerStateKey key; - key.rasterizerState = rasterState; - key.scissorEnabled = scissorEnabled; - key.depthSize = depthSize; - - RasterizerStateMap::iterator i = mRasterizerStateCache.find(key); - if (i != mRasterizerStateCache.end()) - { - RasterizerStateCounterPair &state = i->second; - state.second = mCounter++; - return state.first; - } - else - { - if (mRasterizerStateCache.size() >= kMaxRasterizerStates) - { - TRACE("Overflowed the limit of %u rasterizer states, removing the least recently used " - "to make room.", kMaxRasterizerStates); - - RasterizerStateMap::iterator leastRecentlyUsed = mRasterizerStateCache.begin(); - for (RasterizerStateMap::iterator i = mRasterizerStateCache.begin(); i != mRasterizerStateCache.end(); i++) - { - if (i->second.second < leastRecentlyUsed->second.second) - { - leastRecentlyUsed = i; - } - } - leastRecentlyUsed->second.first->Release(); - mRasterizerStateCache.erase(leastRecentlyUsed); - } - - D3D11_CULL_MODE cullMode = gl_d3d11::ConvertCullMode(rasterState.cullFace, rasterState.cullMode); - - // Disable culling if drawing points - if (rasterState.pointDrawMode) - { - cullMode = D3D11_CULL_NONE; - } - - D3D11_RASTERIZER_DESC rasterDesc; - rasterDesc.FillMode = D3D11_FILL_SOLID; - rasterDesc.CullMode = cullMode; - rasterDesc.FrontCounterClockwise = (rasterState.frontFace == GL_CCW) ? FALSE: TRUE; - rasterDesc.DepthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast(depthSize)); - rasterDesc.DepthBiasClamp = 0.0f; // MSDN documentation of DepthBiasClamp implies a value of zero will preform no clamping, must be tested though. - rasterDesc.SlopeScaledDepthBias = rasterState.polygonOffsetFactor; - rasterDesc.DepthClipEnable = TRUE; - rasterDesc.ScissorEnable = scissorEnabled ? TRUE : FALSE; - rasterDesc.MultisampleEnable = rasterState.multiSample; - rasterDesc.AntialiasedLineEnable = FALSE; - - ID3D11RasterizerState *dx11RasterizerState = NULL; - HRESULT result = mDevice->CreateRasterizerState(&rasterDesc, &dx11RasterizerState); - if (FAILED(result) || !dx11RasterizerState) - { - ERR("Unable to create a ID3D11RasterizerState, HRESULT: 0x%X.", result); - return NULL; - } - - mRasterizerStateCache.insert(std::make_pair(key, std::make_pair(dx11RasterizerState, mCounter++))); - - return dx11RasterizerState; - } -} - -std::size_t RenderStateCache::hashDepthStencilState(const gl::DepthStencilState &dsState) -{ - static const unsigned int seed = 0xABCDEF98; - - std::size_t hash = 0; - MurmurHash3_x86_32(&dsState, sizeof(gl::DepthStencilState), seed, &hash); - return hash; -} - -bool RenderStateCache::compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b) -{ - return memcmp(&a, &b, sizeof(gl::DepthStencilState)) == 0; -} - -ID3D11DepthStencilState *RenderStateCache::getDepthStencilState(const gl::DepthStencilState &dsState) -{ - if (!mDevice) - { - ERR("RenderStateCache is not initialized."); - return NULL; - } - - DepthStencilStateMap::iterator i = mDepthStencilStateCache.find(dsState); - if (i != mDepthStencilStateCache.end()) - { - DepthStencilStateCounterPair &state = i->second; - state.second = mCounter++; - return state.first; - } - else - { - if (mDepthStencilStateCache.size() >= kMaxDepthStencilStates) - { - TRACE("Overflowed the limit of %u depth stencil states, removing the least recently used " - "to make room.", kMaxDepthStencilStates); - - DepthStencilStateMap::iterator leastRecentlyUsed = mDepthStencilStateCache.begin(); - for (DepthStencilStateMap::iterator i = mDepthStencilStateCache.begin(); i != mDepthStencilStateCache.end(); i++) - { - if (i->second.second < leastRecentlyUsed->second.second) - { - leastRecentlyUsed = i; - } - } - leastRecentlyUsed->second.first->Release(); - mDepthStencilStateCache.erase(leastRecentlyUsed); - } - - D3D11_DEPTH_STENCIL_DESC dsDesc = { 0 }; - dsDesc.DepthEnable = dsState.depthTest ? TRUE : FALSE; - dsDesc.DepthWriteMask = gl_d3d11::ConvertDepthMask(dsState.depthMask); - dsDesc.DepthFunc = gl_d3d11::ConvertComparison(dsState.depthFunc); - dsDesc.StencilEnable = dsState.stencilTest ? TRUE : FALSE; - dsDesc.StencilReadMask = gl_d3d11::ConvertStencilMask(dsState.stencilMask); - dsDesc.StencilWriteMask = gl_d3d11::ConvertStencilMask(dsState.stencilWritemask); - dsDesc.FrontFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilFail); - dsDesc.FrontFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthFail); - dsDesc.FrontFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilPassDepthPass); - dsDesc.FrontFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilFunc); - dsDesc.BackFace.StencilFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackFail); - dsDesc.BackFace.StencilDepthFailOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthFail); - dsDesc.BackFace.StencilPassOp = gl_d3d11::ConvertStencilOp(dsState.stencilBackPassDepthPass); - dsDesc.BackFace.StencilFunc = gl_d3d11::ConvertComparison(dsState.stencilBackFunc); - - ID3D11DepthStencilState *dx11DepthStencilState = NULL; - HRESULT result = mDevice->CreateDepthStencilState(&dsDesc, &dx11DepthStencilState); - if (FAILED(result) || !dx11DepthStencilState) - { - ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); - return NULL; - } - - mDepthStencilStateCache.insert(std::make_pair(dsState, std::make_pair(dx11DepthStencilState, mCounter++))); - - return dx11DepthStencilState; - } -} - -std::size_t RenderStateCache::hashSamplerState(const gl::SamplerState &samplerState) -{ - static const unsigned int seed = 0xABCDEF98; - - std::size_t hash = 0; - MurmurHash3_x86_32(&samplerState, sizeof(gl::SamplerState), seed, &hash); - return hash; -} - -bool RenderStateCache::compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b) -{ - return memcmp(&a, &b, sizeof(gl::SamplerState)) == 0; -} - -ID3D11SamplerState *RenderStateCache::getSamplerState(const gl::SamplerState &samplerState) -{ - if (!mDevice) - { - ERR("RenderStateCache is not initialized."); - return NULL; - } - - SamplerStateMap::iterator i = mSamplerStateCache.find(samplerState); - if (i != mSamplerStateCache.end()) - { - SamplerStateCounterPair &state = i->second; - state.second = mCounter++; - return state.first; - } - else - { - if (mSamplerStateCache.size() >= kMaxSamplerStates) - { - TRACE("Overflowed the limit of %u sampler states, removing the least recently used " - "to make room.", kMaxSamplerStates); - - SamplerStateMap::iterator leastRecentlyUsed = mSamplerStateCache.begin(); - for (SamplerStateMap::iterator i = mSamplerStateCache.begin(); i != mSamplerStateCache.end(); i++) - { - if (i->second.second < leastRecentlyUsed->second.second) - { - leastRecentlyUsed = i; - } - } - leastRecentlyUsed->second.first->Release(); - mSamplerStateCache.erase(leastRecentlyUsed); - } - - D3D11_SAMPLER_DESC samplerDesc; - samplerDesc.Filter = gl_d3d11::ConvertFilter(samplerState.minFilter, samplerState.magFilter, samplerState.maxAnisotropy); - samplerDesc.AddressU = gl_d3d11::ConvertTextureWrap(samplerState.wrapS); - samplerDesc.AddressV = gl_d3d11::ConvertTextureWrap(samplerState.wrapT); - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.MipLODBias = static_cast(samplerState.lodOffset); - samplerDesc.MaxAnisotropy = samplerState.maxAnisotropy; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; - samplerDesc.BorderColor[0] = 0.0f; - samplerDesc.BorderColor[1] = 0.0f; - samplerDesc.BorderColor[2] = 0.0f; - samplerDesc.BorderColor[3] = 0.0f; - samplerDesc.MinLOD = gl_d3d11::ConvertMinLOD(samplerState.minFilter, samplerState.lodOffset); - samplerDesc.MaxLOD = mDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 - ? gl_d3d11::ConvertMaxLOD(samplerState.minFilter, samplerState.lodOffset) : FLT_MAX; - - ID3D11SamplerState *dx11SamplerState = NULL; - HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState); - if (FAILED(result) || !dx11SamplerState) - { - ERR("Unable to create a ID3D11DepthStencilState, HRESULT: 0x%X.", result); - return NULL; - } - - mSamplerStateCache.insert(std::make_pair(samplerState, std::make_pair(dx11SamplerState, mCounter++))); - - return dx11SamplerState; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h deleted file mode 100644 index b4b871a4bd..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderStateCache.h +++ /dev/null @@ -1,111 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderStateCache.h: Defines rx::RenderStateCache, a cache of Direct3D render -// state objects. - -#ifndef LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ -#define LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ - -#include "libGLESv2/angletypes.h" -#include "common/angleutils.h" - -namespace gl -{ -class Framebuffer; -} - -namespace rx -{ - -class RenderStateCache -{ - public: - RenderStateCache(); - virtual ~RenderStateCache(); - - void initialize(ID3D11Device *device); - void clear(); - - // Increments refcount on the returned blend state, Release() must be called. - ID3D11BlendState *getBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState); - ID3D11RasterizerState *getRasterizerState(const gl::RasterizerState &rasterState, - bool scissorEnabled, unsigned int depthSize); - ID3D11DepthStencilState *getDepthStencilState(const gl::DepthStencilState &dsState); - ID3D11SamplerState *getSamplerState(const gl::SamplerState &samplerState); - - private: - DISALLOW_COPY_AND_ASSIGN(RenderStateCache); - - unsigned long long mCounter; - - // Blend state cache - struct BlendStateKey - { - gl::BlendState blendState; - bool rtChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4]; - }; - static std::size_t hashBlendState(const BlendStateKey &blendState); - static bool compareBlendStates(const BlendStateKey &a, const BlendStateKey &b); - static const unsigned int kMaxBlendStates; - - typedef std::size_t (*BlendStateHashFunction)(const BlendStateKey &); - typedef bool (*BlendStateEqualityFunction)(const BlendStateKey &, const BlendStateKey &); - typedef std::pair BlendStateCounterPair; - typedef std::unordered_map BlendStateMap; - BlendStateMap mBlendStateCache; - - // Rasterizer state cache - struct RasterizerStateKey - { - gl::RasterizerState rasterizerState; - bool scissorEnabled; - unsigned int depthSize; - }; - static std::size_t hashRasterizerState(const RasterizerStateKey &rasterState); - static bool compareRasterizerStates(const RasterizerStateKey &a, const RasterizerStateKey &b); - static const unsigned int kMaxRasterizerStates; - - typedef std::size_t (*RasterizerStateHashFunction)(const RasterizerStateKey &); - typedef bool (*RasterizerStateEqualityFunction)(const RasterizerStateKey &, const RasterizerStateKey &); - typedef std::pair RasterizerStateCounterPair; - typedef std::unordered_map RasterizerStateMap; - RasterizerStateMap mRasterizerStateCache; - - // Depth stencil state cache - static std::size_t hashDepthStencilState(const gl::DepthStencilState &dsState); - static bool compareDepthStencilStates(const gl::DepthStencilState &a, const gl::DepthStencilState &b); - static const unsigned int kMaxDepthStencilStates; - - typedef std::size_t (*DepthStencilStateHashFunction)(const gl::DepthStencilState &); - typedef bool (*DepthStencilStateEqualityFunction)(const gl::DepthStencilState &, const gl::DepthStencilState &); - typedef std::pair DepthStencilStateCounterPair; - typedef std::unordered_map DepthStencilStateMap; - DepthStencilStateMap mDepthStencilStateCache; - - // Sample state cache - static std::size_t hashSamplerState(const gl::SamplerState &samplerState); - static bool compareSamplerStates(const gl::SamplerState &a, const gl::SamplerState &b); - static const unsigned int kMaxSamplerStates; - - typedef std::size_t (*SamplerStateHashFunction)(const gl::SamplerState &); - typedef bool (*SamplerStateEqualityFunction)(const gl::SamplerState &, const gl::SamplerState &); - typedef std::pair SamplerStateCounterPair; - typedef std::unordered_map SamplerStateMap; - SamplerStateMap mSamplerStateCache; - - ID3D11Device *mDevice; -}; - -} - -#endif // LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp deleted file mode 100644 index 3707097aa4..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.cpp +++ /dev/null @@ -1,355 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers -// retained by Renderbuffers. - -#include "libGLESv2/renderer/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" - -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -static unsigned int getRTVSubresourceIndex(ID3D11Texture2D *texture, ID3D11RenderTargetView *view) -{ - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - view->GetDesc(&rtvDesc); - - D3D11_TEXTURE2D_DESC texDesc; - texture->GetDesc(&texDesc); - - unsigned int mipSlice = 0; - unsigned int arraySlice = 0; - unsigned int mipLevels = texDesc.MipLevels; - - switch (rtvDesc.ViewDimension) - { - case D3D11_RTV_DIMENSION_TEXTURE1D: - mipSlice = rtvDesc.Texture1D.MipSlice; - arraySlice = 0; - break; - - case D3D11_RTV_DIMENSION_TEXTURE1DARRAY: - mipSlice = rtvDesc.Texture1DArray.MipSlice; - arraySlice = rtvDesc.Texture1DArray.FirstArraySlice; - break; - - case D3D11_RTV_DIMENSION_TEXTURE2D: - mipSlice = rtvDesc.Texture2D.MipSlice; - arraySlice = 0; - break; - - case D3D11_RTV_DIMENSION_TEXTURE2DARRAY: - mipSlice = rtvDesc.Texture2DArray.MipSlice; - arraySlice = rtvDesc.Texture2DArray.FirstArraySlice; - break; - - case D3D11_RTV_DIMENSION_TEXTURE2DMS: - mipSlice = 0; - arraySlice = 0; - break; - - case D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY: - mipSlice = 0; - arraySlice = rtvDesc.Texture2DMSArray.FirstArraySlice; - break; - - case D3D11_RTV_DIMENSION_TEXTURE3D: - mipSlice = rtvDesc.Texture3D.MipSlice; - arraySlice = 0; - break; - - case D3D11_RTV_DIMENSION_UNKNOWN: - case D3D11_RTV_DIMENSION_BUFFER: - UNIMPLEMENTED(); - break; - - default: - UNREACHABLE(); - break; - } - - return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); -} - -static unsigned int getDSVSubresourceIndex(ID3D11Texture2D *texture, ID3D11DepthStencilView *view) -{ - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - view->GetDesc(&dsvDesc); - - D3D11_TEXTURE2D_DESC texDesc; - texture->GetDesc(&texDesc); - - unsigned int mipSlice = 0; - unsigned int arraySlice = 0; - unsigned int mipLevels = texDesc.MipLevels; - - switch (dsvDesc.ViewDimension) - { - case D3D11_DSV_DIMENSION_TEXTURE1D: - mipSlice = dsvDesc.Texture1D.MipSlice; - arraySlice = 0; - break; - - case D3D11_DSV_DIMENSION_TEXTURE1DARRAY: - mipSlice = dsvDesc.Texture1DArray.MipSlice; - arraySlice = dsvDesc.Texture1DArray.FirstArraySlice; - break; - - case D3D11_DSV_DIMENSION_TEXTURE2D: - mipSlice = dsvDesc.Texture2D.MipSlice; - arraySlice = 0; - break; - - case D3D11_DSV_DIMENSION_TEXTURE2DARRAY: - mipSlice = dsvDesc.Texture2DArray.MipSlice; - arraySlice = dsvDesc.Texture2DArray.FirstArraySlice; - break; - - case D3D11_DSV_DIMENSION_TEXTURE2DMS: - mipSlice = 0; - arraySlice = 0; - break; - - case D3D11_DSV_DIMENSION_TEXTURE2DMSARRAY: - mipSlice = 0; - arraySlice = dsvDesc.Texture2DMSArray.FirstArraySlice; - break; - - case D3D11_RTV_DIMENSION_UNKNOWN: - UNIMPLEMENTED(); - break; - - default: - UNREACHABLE(); - break; - } - - return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels); -} - -RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height) -{ - mRenderer = Renderer11::makeRenderer11(renderer); - mTexture = tex; - mRenderTarget = rtv; - mDepthStencil = NULL; - mShaderResource = srv; - mSubresourceIndex = 0; - - if (mRenderTarget && mTexture) - { - D3D11_RENDER_TARGET_VIEW_DESC desc; - mRenderTarget->GetDesc(&desc); - - D3D11_TEXTURE2D_DESC texDesc; - mTexture->GetDesc(&texDesc); - - mSubresourceIndex = getRTVSubresourceIndex(mTexture, mRenderTarget); - mWidth = width; - mHeight = height; - mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0; - - mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); - mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); - } -} - -RenderTarget11::RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height) -{ - mRenderer = Renderer11::makeRenderer11(renderer); - mTexture = tex; - mRenderTarget = NULL; - mDepthStencil = dsv; - mShaderResource = srv; - mSubresourceIndex = 0; - - if (mDepthStencil && mTexture) - { - D3D11_DEPTH_STENCIL_VIEW_DESC desc; - mDepthStencil->GetDesc(&desc); - - D3D11_TEXTURE2D_DESC texDesc; - mTexture->GetDesc(&texDesc); - - mSubresourceIndex = getDSVSubresourceIndex(mTexture, mDepthStencil); - mWidth = width; - mHeight = height; - mSamples = (texDesc.SampleDesc.Count > 1) ? texDesc.SampleDesc.Count : 0; - - mInternalFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); - mActualFormat = d3d11_gl::ConvertTextureInternalFormat(desc.Format); - } -} - -RenderTarget11::RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth) -{ - mRenderer = Renderer11::makeRenderer11(renderer); - mTexture = NULL; - mRenderTarget = NULL; - mDepthStencil = NULL; - mShaderResource = NULL; - - DXGI_FORMAT requestedFormat = gl_d3d11::ConvertRenderbufferFormat(format); - - int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples); - if (supportedSamples < 0) - { - gl::error(GL_OUT_OF_MEMORY); - return; - } - - if (width > 0 && height > 0) - { - // Create texture resource - D3D11_TEXTURE2D_DESC desc; - desc.Width = width; - desc.Height = height; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = requestedFormat; - desc.SampleDesc.Count = (supportedSamples == 0) ? 1 : supportedSamples; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - desc.BindFlags = (depth ? D3D11_BIND_DEPTH_STENCIL : (D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE)); - - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); - - if (result == E_OUTOFMEMORY) - { - gl::error(GL_OUT_OF_MEMORY); - return; - } - ASSERT(SUCCEEDED(result)); - - if (depth) - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = requestedFormat; - dsvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; - dsvDesc.Texture2D.MipSlice = 0; - dsvDesc.Flags = 0; - result = device->CreateDepthStencilView(mTexture, &dsvDesc, &mDepthStencil); - - if (result == E_OUTOFMEMORY) - { - mTexture->Release(); - mTexture = NULL; - gl::error(GL_OUT_OF_MEMORY); - } - ASSERT(SUCCEEDED(result)); - } - else - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = requestedFormat; - rtvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; - rtvDesc.Texture2D.MipSlice = 0; - result = device->CreateRenderTargetView(mTexture, &rtvDesc, &mRenderTarget); - - if (result == E_OUTOFMEMORY) - { - mTexture->Release(); - mTexture = NULL; - gl::error(GL_OUT_OF_MEMORY); - return; - } - ASSERT(SUCCEEDED(result)); - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = requestedFormat; - srvDesc.ViewDimension = (supportedSamples == 0) ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS; - srvDesc.Texture2D.MostDetailedMip = 0; - srvDesc.Texture2D.MipLevels = 1; - result = device->CreateShaderResourceView(mTexture, &srvDesc, &mShaderResource); - - if (result == E_OUTOFMEMORY) - { - mTexture->Release(); - mTexture = NULL; - mRenderTarget->Release(); - mRenderTarget = NULL; - gl::error(GL_OUT_OF_MEMORY); - return; - } - ASSERT(SUCCEEDED(result)); - } - } - - mWidth = width; - mHeight = height; - mInternalFormat = format; - mSamples = supportedSamples; - mActualFormat = d3d11_gl::ConvertTextureInternalFormat(requestedFormat); - mSubresourceIndex = D3D11CalcSubresource(0, 0, 1); -} - -RenderTarget11::~RenderTarget11() -{ - if (mTexture) - { - mTexture->Release(); - mTexture = NULL; - } - - if (mRenderTarget) - { - mRenderTarget->Release(); - mRenderTarget = NULL; - } - - if (mDepthStencil) - { - mDepthStencil->Release(); - mDepthStencil = NULL; - } - - if (mShaderResource) - { - mShaderResource->Release(); - mShaderResource = NULL; - } -} - -RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget11*, target)); - return static_cast(target); -} - -ID3D11Texture2D *RenderTarget11::getTexture() const -{ - return mTexture; -} - -ID3D11RenderTargetView *RenderTarget11::getRenderTargetView() const -{ - return mRenderTarget; -} - -ID3D11DepthStencilView *RenderTarget11::getDepthStencilView() const -{ - return mDepthStencil; -} - -ID3D11ShaderResourceView *RenderTarget11::getShaderResourceView() const -{ - return mShaderResource; -} - -unsigned int RenderTarget11::getSubresourceIndex() const -{ - return mSubresourceIndex; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h deleted file mode 100644 index 97827f2639..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/RenderTarget11.h +++ /dev/null @@ -1,51 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderTarget11.h: Defines a DX11-specific wrapper for ID3D11View pointers -// retained by Renderbuffers. - -#ifndef LIBGLESV2_RENDERER_RENDERTARGET11_H_ -#define LIBGLESV2_RENDERER_RENDERTARGET11_H_ - -#include "libGLESv2/renderer/RenderTarget.h" - -namespace rx -{ -class Renderer; -class Renderer11; - -class RenderTarget11 : public RenderTarget -{ - public: - RenderTarget11(Renderer *renderer, ID3D11RenderTargetView *rtv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height); - RenderTarget11(Renderer *renderer, ID3D11DepthStencilView *dsv, ID3D11Texture2D *tex, ID3D11ShaderResourceView *srv, GLsizei width, GLsizei height); - RenderTarget11(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples, bool depth); - virtual ~RenderTarget11(); - - static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget); - - ID3D11Texture2D *getTexture() const; - ID3D11RenderTargetView *getRenderTargetView() const; - ID3D11DepthStencilView *getDepthStencilView() const; - ID3D11ShaderResourceView *getShaderResourceView() const; - - unsigned int getSubresourceIndex() const; - - private: - DISALLOW_COPY_AND_ASSIGN(RenderTarget11); - - unsigned int mSubresourceIndex; - ID3D11Texture2D *mTexture; - ID3D11RenderTargetView *mRenderTarget; - ID3D11DepthStencilView *mDepthStencil; - ID3D11ShaderResourceView *mShaderResource; - - Renderer11 *mRenderer; -}; - -} - -#endif LIBGLESV2_RENDERER_RENDERTARGET11_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp deleted file mode 100644 index e70727c65e..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp +++ /dev/null @@ -1,3736 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer. - -#include "libGLESv2/main.h" -#include "libGLESv2/utilities.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h" -#include "libGLESv2/renderer/d3d11/SwapChain11.h" -#include "libGLESv2/renderer/d3d11/Image11.h" -#include "libGLESv2/renderer/d3d11/VertexBuffer11.h" -#include "libGLESv2/renderer/d3d11/IndexBuffer11.h" -#include "libGLESv2/renderer/d3d11/BufferStorage11.h" -#include "libGLESv2/renderer/VertexDataManager.h" -#include "libGLESv2/renderer/IndexDataManager.h" -#include "libGLESv2/renderer/d3d11/TextureStorage11.h" -#include "libGLESv2/renderer/d3d11/Query11.h" -#include "libGLESv2/renderer/d3d11/Fence11.h" - -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgb11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlum11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughlumalpha11ps.h" - -#include "libGLESv2/renderer/d3d11/shaders/compiled/clear11vs.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/clearsingle11ps.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/clearmultiple11ps.h" - -#include "libEGL/Display.h" - -#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) -# include -# include -# include -typedef ABI::Windows::Foundation::IEventHandler SuspendEventHandler; -#endif - -#ifdef _DEBUG -// this flag enables suppressing some spurious warnings that pop up in certain WebGL samples -// and conformance tests. to enable all warnings, remove this define. -#define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1 -#endif - -namespace rx -{ -static const DXGI_FORMAT RenderTargetFormats[] = - { - DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_FORMAT_R8G8B8A8_UNORM - }; - -static const DXGI_FORMAT DepthStencilFormats[] = - { - DXGI_FORMAT_UNKNOWN, - DXGI_FORMAT_D24_UNORM_S8_UINT, - DXGI_FORMAT_D16_UNORM - }; - -enum -{ - MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 = 16 -}; - -Renderer11::Renderer11(egl::Display *display) : Renderer(display) -{ - mVertexDataManager = NULL; - mIndexDataManager = NULL; - - mLineLoopIB = NULL; - mTriangleFanIB = NULL; - - mCopyResourcesInitialized = false; - mCopyVB = NULL; - mCopySampler = NULL; - mCopyIL = NULL; - mCopyVS = NULL; - mCopyRGBAPS = NULL; - mCopyRGBPS = NULL; - mCopyLumPS = NULL; - mCopyLumAlphaPS = NULL; - - mClearResourcesInitialized = false; - mClearVB = NULL; - mClearIL = NULL; - mClearVS = NULL; - mClearSinglePS = NULL; - mClearMultiplePS = NULL; - mClearScissorRS = NULL; - mClearNoScissorRS = NULL; - - mSyncQuery = NULL; - - mD3d11Module = NULL; - mDxgiModule = NULL; - - mDeviceLost = false; - - mMaxSupportedSamples = 0; - - mDevice = NULL; - mDeviceContext = NULL; - mDxgiAdapter = NULL; - mDxgiFactory = NULL; - - mDriverConstantBufferVS = NULL; - mDriverConstantBufferPS = NULL; - - mBGRATextureSupport = false; - - mIsGeometryShaderActive = false; -} - -Renderer11::~Renderer11() -{ - release(); -} - -Renderer11 *Renderer11::makeRenderer11(Renderer *renderer) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer11*, renderer)); - return static_cast(renderer); -} - -#ifndef __d3d11_1_h__ -#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081) -#endif - -EGLint Renderer11::initialize() -{ - if (!initializeCompiler()) - { - return EGL_NOT_INITIALIZED; - } - -#if !defined(ANGLE_OS_WINRT) - mDxgiModule = LoadLibrary(TEXT("dxgi.dll")); - mD3d11Module = LoadLibrary(TEXT("d3d11.dll")); - - if (mD3d11Module == NULL || mDxgiModule == NULL) - { - ERR("Could not load D3D11 or DXGI library - aborting!\n"); - return EGL_NOT_INITIALIZED; - } - - - // create the D3D11 device - ASSERT(mDevice == NULL); - PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); - - if (D3D11CreateDevice == NULL) - { - ERR("Could not retrieve D3D11CreateDevice address - aborting!\n"); - return EGL_NOT_INITIALIZED; - } -#endif - - D3D_FEATURE_LEVEL featureLevels[] = - { - D3D_FEATURE_LEVEL_11_0, - D3D_FEATURE_LEVEL_10_1, - D3D_FEATURE_LEVEL_10_0, -#if !defined(ANGLE_ENABLE_D3D9) - D3D_FEATURE_LEVEL_9_3, - D3D_FEATURE_LEVEL_9_2, - D3D_FEATURE_LEVEL_9_1, -#endif - }; - - HRESULT result = S_OK; - -#ifdef _DEBUG - result = D3D11CreateDevice(NULL, - D3D_DRIVER_TYPE_HARDWARE, - NULL, - D3D11_CREATE_DEVICE_DEBUG, - featureLevels, - ArraySize(featureLevels), - D3D11_SDK_VERSION, - &mDevice, - &mFeatureLevel, - &mDeviceContext); - - if (!mDevice || FAILED(result)) - { - ERR("Failed creating Debug D3D11 device - falling back to release runtime.\n"); - } - - if (!mDevice || FAILED(result)) -#endif - { - result = D3D11CreateDevice(NULL, - D3D_DRIVER_TYPE_HARDWARE, - NULL, - 0, - featureLevels, - ArraySize(featureLevels), - D3D11_SDK_VERSION, - &mDevice, - &mFeatureLevel, - &mDeviceContext); - - if (!mDevice || FAILED(result)) - { - ERR("Could not create D3D11 device - aborting!\n"); - return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer - } - } - -#if !defined(ANGLE_OS_WINRT) - IDXGIDevice *dxgiDevice = NULL; -#else - IDXGIDevice1 *dxgiDevice = NULL; -#endif - result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice)); - - if (FAILED(result)) - { - ERR("Could not query DXGI device - aborting!\n"); - return EGL_NOT_INITIALIZED; - } - - result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter); - - if (FAILED(result)) - { - ERR("Could not retrieve DXGI adapter - aborting!\n"); - return EGL_NOT_INITIALIZED; - } - - dxgiDevice->Release(); - - mDxgiAdapter->GetDesc(&mAdapterDescription); - memset(mDescription, 0, sizeof(mDescription)); - wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1); - - result = mDxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&mDxgiFactory); - - if (!mDxgiFactory || FAILED(result)) - { - ERR("Could not create DXGI factory - aborting!\n"); - return EGL_NOT_INITIALIZED; - } - - // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log -#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG) - ID3D11InfoQueue *infoQueue; - result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue); - - if (SUCCEEDED(result)) - { - D3D11_MESSAGE_ID hideMessages[] = - { - D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET - }; - - D3D11_INFO_QUEUE_FILTER filter = {0}; - filter.DenyList.NumIDs = ArraySize(hideMessages); - filter.DenyList.pIDList = hideMessages; - - infoQueue->AddStorageFilterEntries(&filter); - - infoQueue->Release(); - } -#endif - - unsigned int maxSupportedSamples = 0; - unsigned int rtFormatCount = ArraySize(RenderTargetFormats); - unsigned int dsFormatCount = ArraySize(DepthStencilFormats); - for (unsigned int i = 0; i < rtFormatCount + dsFormatCount; ++i) - { - DXGI_FORMAT format = (i < rtFormatCount) ? RenderTargetFormats[i] : DepthStencilFormats[i - rtFormatCount]; - if (format != DXGI_FORMAT_UNKNOWN) - { - UINT formatSupport; - result = mDevice->CheckFormatSupport(format, &formatSupport); - if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_MULTISAMPLE_RENDERTARGET)) - { - MultisampleSupportInfo supportInfo; - - for (unsigned int j = 1; j <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; j++) - { - result = mDevice->CheckMultisampleQualityLevels(format, j, &supportInfo.qualityLevels[j - 1]); - if (SUCCEEDED(result) && supportInfo.qualityLevels[j - 1] > 0) - { - maxSupportedSamples = std::max(j, maxSupportedSamples); - } - else - { - supportInfo.qualityLevels[j - 1] = 0; - } - } - - mMultisampleSupportMap.insert(std::make_pair(format, supportInfo)); - } - } - } - mMaxSupportedSamples = maxSupportedSamples; - - initializeDevice(); - - // BGRA texture support is optional in feature levels 10 and 10_1 - UINT formatSupport; - result = mDevice->CheckFormatSupport(DXGI_FORMAT_B8G8R8A8_UNORM, &formatSupport); - if (FAILED(result)) - { - ERR("Error checking BGRA format support: 0x%08X", result); - } - else - { - const int flags = (D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_RENDER_TARGET); - mBGRATextureSupport = (formatSupport & flags) == flags; - } - - // Check floating point texture support - static const unsigned int requiredTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE; - static const unsigned int requiredRenderableFlags = D3D11_FORMAT_SUPPORT_RENDER_TARGET; - static const unsigned int requiredFilterFlags = D3D11_FORMAT_SUPPORT_SHADER_SAMPLE; - - DXGI_FORMAT float16Formats[] = - { - DXGI_FORMAT_R16_FLOAT, - DXGI_FORMAT_R16G16_FLOAT, - DXGI_FORMAT_R16G16B16A16_FLOAT, - }; - - DXGI_FORMAT float32Formats[] = - { - DXGI_FORMAT_R32_FLOAT, - DXGI_FORMAT_R32G32_FLOAT, - DXGI_FORMAT_R32G32B32A32_FLOAT, - }; - - mFloat16TextureSupport = true; - mFloat16FilterSupport = true; - mFloat16RenderSupport = true; - for (unsigned int i = 0; i < ArraySize(float16Formats); i++) - { - if (SUCCEEDED(mDevice->CheckFormatSupport(float16Formats[i], &formatSupport))) - { - mFloat16TextureSupport = mFloat16TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags; - mFloat16FilterSupport = mFloat16FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags; - mFloat16RenderSupport = mFloat16RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags; - } - else - { - mFloat16TextureSupport = false; - mFloat16RenderSupport = false; - mFloat16FilterSupport = false; - } - } - - mFloat32TextureSupport = true; - mFloat32FilterSupport = true; - mFloat32RenderSupport = true; - for (unsigned int i = 0; i < ArraySize(float32Formats); i++) - { - if (SUCCEEDED(mDevice->CheckFormatSupport(float32Formats[i], &formatSupport))) - { - mFloat32TextureSupport = mFloat32TextureSupport && (formatSupport & requiredTextureFlags) == requiredTextureFlags; - mFloat32FilterSupport = mFloat32FilterSupport && (formatSupport & requiredFilterFlags) == requiredFilterFlags; - mFloat32RenderSupport = mFloat32RenderSupport && (formatSupport & requiredRenderableFlags) == requiredRenderableFlags; - } - else - { - mFloat32TextureSupport = false; - mFloat32FilterSupport = false; - mFloat32RenderSupport = false; - } - } - - // Check compressed texture support - const unsigned int requiredCompressedTextureFlags = D3D11_FORMAT_SUPPORT_TEXTURE2D; - - if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC1_UNORM, &formatSupport))) - { - mDXT1TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; - } - else - { - mDXT1TextureSupport = false; - } - - if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC3_UNORM, &formatSupport))) - { - mDXT3TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; - } - else - { - mDXT3TextureSupport = false; - } - - if (SUCCEEDED(mDevice->CheckFormatSupport(DXGI_FORMAT_BC5_UNORM, &formatSupport))) - { - mDXT5TextureSupport = (formatSupport & requiredCompressedTextureFlags) == requiredCompressedTextureFlags; - } - else - { - mDXT5TextureSupport = false; - } - - // Check depth texture support - DXGI_FORMAT depthTextureFormats[] = - { - DXGI_FORMAT_D16_UNORM, - DXGI_FORMAT_D24_UNORM_S8_UINT, - }; - - static const unsigned int requiredDepthTextureFlags = D3D11_FORMAT_SUPPORT_DEPTH_STENCIL | - D3D11_FORMAT_SUPPORT_TEXTURE2D; - - mDepthTextureSupport = true; - for (unsigned int i = 0; i < ArraySize(depthTextureFormats); i++) - { - if (SUCCEEDED(mDevice->CheckFormatSupport(depthTextureFormats[i], &formatSupport))) - { - mDepthTextureSupport = mDepthTextureSupport && ((formatSupport & requiredDepthTextureFlags) == requiredDepthTextureFlags); - } - else - { - mDepthTextureSupport = false; - } - } - -#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) - // Monitor when the application suspends so that Trim() can be called - Microsoft::WRL::ComPtr application; - result = RoGetActivationFactory(Microsoft::WRL::Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), - IID_PPV_ARGS(&application)); - if (FAILED(result)) - { - ERR("Error obtaining CoreApplication: 0x%08X", result); - return EGL_NOT_INITIALIZED; - } - - EventRegistrationToken cookie; - result = application->add_Suspending(Microsoft::WRL::Callback(this, &Renderer11::onSuspend).Get(), &cookie); - if (FAILED(result)) - { - ERR("Error setting suspend callback: 0x%08X", result); - return EGL_NOT_INITIALIZED; - } -#endif - - return EGL_SUCCESS; -} - -#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) -HRESULT Renderer11::onSuspend(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *) -{ - if (!mDevice) - return S_OK; - - Microsoft::WRL::ComPtr dxgiDevice; - HRESULT result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice)); - if (FAILED(result)) - { - ERR("Error obtaining DXGIDevice3 on suspend: 0x%08X", result); - return S_OK; - } - - dxgiDevice->Trim(); - - return S_OK; -} -#endif - -// do any one-time device initialization -// NOTE: this is also needed after a device lost/reset -// to reset the scene status and ensure the default states are reset. -void Renderer11::initializeDevice() -{ - mStateCache.initialize(mDevice); - mInputLayoutCache.initialize(mDevice, mDeviceContext); - - ASSERT(!mVertexDataManager && !mIndexDataManager); - mVertexDataManager = new VertexDataManager(this); - mIndexDataManager = new IndexDataManager(this); - - markAllStateDirty(); -} - -int Renderer11::generateConfigs(ConfigDesc **configDescList) -{ - unsigned int numRenderFormats = ArraySize(RenderTargetFormats); - unsigned int numDepthFormats = ArraySize(DepthStencilFormats); - (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; - int numConfigs = 0; - - for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) - { - for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) - { - DXGI_FORMAT renderTargetFormat = RenderTargetFormats[formatIndex]; - - UINT formatSupport = 0; - HRESULT result = mDevice->CheckFormatSupport(renderTargetFormat, &formatSupport); - - if (SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)) - { - DXGI_FORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; - - bool depthStencilFormatOK = true; - - if (depthStencilFormat != DXGI_FORMAT_UNKNOWN) - { - UINT formatSupport = 0; - result = mDevice->CheckFormatSupport(depthStencilFormat, &formatSupport); - depthStencilFormatOK = SUCCEEDED(result) && (formatSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL); - } - - if (depthStencilFormatOK) - { - ConfigDesc newConfig; - newConfig.renderTargetFormat = d3d11_gl::ConvertBackBufferFormat(renderTargetFormat); - newConfig.depthStencilFormat = d3d11_gl::ConvertDepthStencilFormat(depthStencilFormat); - newConfig.multiSample = 0; // FIXME: enumerate multi-sampling - newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast - - (*configDescList)[numConfigs++] = newConfig; - } - } - } - } - - return numConfigs; -} - -void Renderer11::deleteConfigs(ConfigDesc *configDescList) -{ - delete [] (configDescList); -} - -void Renderer11::sync(bool block) -{ - if (block) - { - HRESULT result; - - if (!mSyncQuery) - { - D3D11_QUERY_DESC queryDesc; - queryDesc.Query = D3D11_QUERY_EVENT; - queryDesc.MiscFlags = 0; - - result = mDevice->CreateQuery(&queryDesc, &mSyncQuery); - ASSERT(SUCCEEDED(result)); - } - - mDeviceContext->End(mSyncQuery); - mDeviceContext->Flush(); - - do - { - result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH); - - // Keep polling, but allow other threads to do something useful first - Sleep(0); - - if (testDeviceLost(true)) - { - return; - } - } - while (result == S_FALSE); - } - else - { - mDeviceContext->Flush(); - } -} - -SwapChain *Renderer11::createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) -{ - return new rx::SwapChain11(this, window, shareHandle, backBufferFormat, depthBufferFormat); -} - -void Renderer11::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) -{ - if (type == gl::SAMPLER_PIXEL) - { - if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS) - { - ERR("Pixel shader sampler index %i is not valid.", index); - return; - } - - if (mForceSetPixelSamplerStates[index] || memcmp(&samplerState, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0) - { - ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState); - - if (!dxSamplerState) - { - ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default" - "sampler state for pixel shaders at slot %i.", index); - } - - mDeviceContext->PSSetSamplers(index, 1, &dxSamplerState); - - mCurPixelSamplerStates[index] = samplerState; - } - - mForceSetPixelSamplerStates[index] = false; - } - else if (type == gl::SAMPLER_VERTEX) - { - if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) - { - ERR("Vertex shader sampler index %i is not valid.", index); - return; - } - - if (mForceSetVertexSamplerStates[index] || memcmp(&samplerState, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0) - { - ID3D11SamplerState *dxSamplerState = mStateCache.getSamplerState(samplerState); - - if (!dxSamplerState) - { - ERR("NULL sampler state returned by RenderStateCache::getSamplerState, setting the default" - "sampler state for vertex shaders at slot %i.", index); - } - - mDeviceContext->VSSetSamplers(index, 1, &dxSamplerState); - - mCurVertexSamplerStates[index] = samplerState; - } - - mForceSetVertexSamplerStates[index] = false; - } - else UNREACHABLE(); -} - -void Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *texture) -{ - ID3D11ShaderResourceView *textureSRV = NULL; - unsigned int serial = 0; - bool forceSetTexture = false; - - if (texture) - { - TextureStorageInterface *texStorage = texture->getNativeTexture(); - if (texStorage) - { - TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage->getStorageInstance()); - textureSRV = storage11->getSRV(); - } - - // If we get NULL back from getSRV here, something went wrong in the texture class and we're unexpectedly - // missing the shader resource view - ASSERT(textureSRV != NULL); - - serial = texture->getTextureSerial(); - forceSetTexture = texture->hasDirtyImages(); - } - - if (type == gl::SAMPLER_PIXEL) - { - if (index < 0 || index >= gl::MAX_TEXTURE_IMAGE_UNITS) - { - ERR("Pixel shader sampler index %i is not valid.", index); - return; - } - - if (forceSetTexture || mCurPixelTextureSerials[index] != serial) - { - mDeviceContext->PSSetShaderResources(index, 1, &textureSRV); - } - - mCurPixelTextureSerials[index] = serial; - } - else if (type == gl::SAMPLER_VERTEX) - { - if (index < 0 || index >= (int)getMaxVertexTextureImageUnits()) - { - ERR("Vertex shader sampler index %i is not valid.", index); - return; - } - - if (forceSetTexture || mCurVertexTextureSerials[index] != serial) - { - mDeviceContext->VSSetShaderResources(index, 1, &textureSRV); - } - - mCurVertexTextureSerials[index] = serial; - } - else UNREACHABLE(); -} - -void Renderer11::setRasterizerState(const gl::RasterizerState &rasterState) -{ - if (mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0) - { - ID3D11RasterizerState *dxRasterState = mStateCache.getRasterizerState(rasterState, mScissorEnabled, - mCurDepthSize); - if (!dxRasterState) - { - ERR("NULL rasterizer state returned by RenderStateCache::getRasterizerState, setting the default" - "rasterizer state."); - } - - mDeviceContext->RSSetState(dxRasterState); - - mCurRasterState = rasterState; - } - - mForceSetRasterState = false; -} - -void Renderer11::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, - unsigned int sampleMask) -{ - if (mForceSetBlendState || - memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0 || - memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0 || - sampleMask != mCurSampleMask) - { - ID3D11BlendState *dxBlendState = mStateCache.getBlendState(framebuffer, blendState); - if (!dxBlendState) - { - ERR("NULL blend state returned by RenderStateCache::getBlendState, setting the default " - "blend state."); - } - - float blendColors[4] = {0.0f}; - if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && - blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) - { - blendColors[0] = blendColor.red; - blendColors[1] = blendColor.green; - blendColors[2] = blendColor.blue; - blendColors[3] = blendColor.alpha; - } - else - { - blendColors[0] = blendColor.alpha; - blendColors[1] = blendColor.alpha; - blendColors[2] = blendColor.alpha; - blendColors[3] = blendColor.alpha; - } - - mDeviceContext->OMSetBlendState(dxBlendState, blendColors, sampleMask); - - mCurBlendState = blendState; - mCurBlendColor = blendColor; - mCurSampleMask = sampleMask; - } - - mForceSetBlendState = false; -} - -void Renderer11::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW) -{ - if (mForceSetDepthStencilState || - memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0 || - stencilRef != mCurStencilRef || stencilBackRef != mCurStencilBackRef) - { - if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || - stencilRef != stencilBackRef || - depthStencilState.stencilMask != depthStencilState.stencilBackMask) - { - ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are " - "invalid under WebGL."); - return gl::error(GL_INVALID_OPERATION); - } - - ID3D11DepthStencilState *dxDepthStencilState = mStateCache.getDepthStencilState(depthStencilState); - if (!dxDepthStencilState) - { - ERR("NULL depth stencil state returned by RenderStateCache::getDepthStencilState, " - "setting the default depth stencil state."); - } - - mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, static_cast(stencilRef)); - - mCurDepthStencilState = depthStencilState; - mCurStencilRef = stencilRef; - mCurStencilBackRef = stencilBackRef; - } - - mForceSetDepthStencilState = false; -} - -void Renderer11::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) -{ - if (mForceSetScissor || memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || - enabled != mScissorEnabled) - { - if (enabled) - { - D3D11_RECT rect; - rect.left = std::max(0, scissor.x); - rect.top = std::max(0, scissor.y); - rect.right = scissor.x + std::max(0, scissor.width); - rect.bottom = scissor.y + std::max(0, scissor.height); - - mDeviceContext->RSSetScissorRects(1, &rect); - } - - if (enabled != mScissorEnabled) - { - mForceSetRasterState = true; - } - - mCurScissor = scissor; - mScissorEnabled = enabled; - } - - mForceSetScissor = false; -} - -bool Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport) -{ - gl::Rectangle actualViewport = viewport; - float actualZNear = gl::clamp01(zNear); - float actualZFar = gl::clamp01(zFar); - if (ignoreViewport) - { - actualViewport.x = 0; - actualViewport.y = 0; - actualViewport.width = mRenderTargetDesc.width; - actualViewport.height = mRenderTargetDesc.height; - actualZNear = 0.0f; - actualZFar = 1.0f; - } - - // Get D3D viewport bounds, which depends on the feature level - const Range& viewportBounds = getViewportBounds(); - - // Clamp width and height first to the gl maximum, then clamp further if we extend past the D3D maximum bounds - D3D11_VIEWPORT dxViewport; - dxViewport.TopLeftX = gl::clamp(actualViewport.x, viewportBounds.start, viewportBounds.end); - dxViewport.TopLeftY = gl::clamp(actualViewport.y, viewportBounds.start, viewportBounds.end); - dxViewport.Width = gl::clamp(actualViewport.width, 0, getMaxViewportDimension()); - dxViewport.Height = gl::clamp(actualViewport.height, 0, getMaxViewportDimension()); - dxViewport.Width = std::min((int)dxViewport.Width, viewportBounds.end - static_cast(dxViewport.TopLeftX)); - dxViewport.Height = std::min((int)dxViewport.Height, viewportBounds.end - static_cast(dxViewport.TopLeftY)); - dxViewport.MinDepth = actualZNear; - dxViewport.MaxDepth = actualZFar; - - if (dxViewport.Width <= 0 || dxViewport.Height <= 0) - { - return false; // Nothing to render - } - - bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || - actualZNear != mCurNear || actualZFar != mCurFar; - - if (viewportChanged) - { - mDeviceContext->RSSetViewports(1, &dxViewport); - - mCurViewport = actualViewport; - mCurNear = actualZNear; - mCurFar = actualZFar; - - mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f; - mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f; - mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); - mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); - - mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f; - mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f; - - mVertexConstants.depthRange[0] = actualZNear; - mVertexConstants.depthRange[1] = actualZFar; - mVertexConstants.depthRange[2] = actualZFar - actualZNear; - - mPixelConstants.depthRange[0] = actualZNear; - mPixelConstants.depthRange[1] = actualZFar; - mPixelConstants.depthRange[2] = actualZFar - actualZNear; - } - - mForceSetViewport = false; - return true; -} - -bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count) -{ - D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; - - GLsizei minCount = 0; - - switch (mode) - { - case GL_POINTS: primitiveTopology = D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; minCount = 1; break; - case GL_LINES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINELIST; minCount = 2; break; - case GL_LINE_LOOP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; - case GL_LINE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_LINESTRIP; minCount = 2; break; - case GL_TRIANGLES: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; - case GL_TRIANGLE_STRIP: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; minCount = 3; break; - // emulate fans via rewriting index buffer - case GL_TRIANGLE_FAN: primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST; minCount = 3; break; - default: - return gl::error(GL_INVALID_ENUM, false); - } - - if (primitiveTopology != mCurrentPrimitiveTopology) - { - mDeviceContext->IASetPrimitiveTopology(primitiveTopology); - mCurrentPrimitiveTopology = primitiveTopology; - } - - return count >= minCount; -} - -bool Renderer11::applyRenderTarget(gl::Framebuffer *framebuffer) -{ - // Get the color render buffer and serial - // Also extract the render target dimensions and view - unsigned int renderTargetWidth = 0; - unsigned int renderTargetHeight = 0; - GLenum renderTargetFormat = 0; - unsigned int renderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {0}; - ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; - bool missingColorRenderTarget = true; - - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - const GLenum drawBufferState = framebuffer->getDrawBufferState(colorAttachment); - - if (framebuffer->getColorbufferType(colorAttachment) != GL_NONE && drawBufferState != GL_NONE) - { - // the draw buffer must be either "none", "back" for the default buffer or the same index as this color (in order) - ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment)); - - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(colorAttachment); - - if (!colorbuffer) - { - ERR("render target pointer unexpectedly null."); - return false; - } - - // check for zero-sized default framebuffer, which is a special case. - // in this case we do not wish to modify any state and just silently return false. - // this will not report any gl error but will cause the calling method to return. - if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) - { - return false; - } - - renderTargetSerials[colorAttachment] = colorbuffer->getSerial(); - - // Extract the render target dimensions and view - RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); - if (!renderTarget) - { - ERR("render target pointer unexpectedly null."); - return false; - } - - framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); - if (!framebufferRTVs[colorAttachment]) - { - ERR("render target view pointer unexpectedly null."); - return false; - } - - if (missingColorRenderTarget) - { - renderTargetWidth = colorbuffer->getWidth(); - renderTargetHeight = colorbuffer->getHeight(); - renderTargetFormat = colorbuffer->getActualFormat(); - missingColorRenderTarget = false; - } - -#ifdef _DEBUG - // Workaround for Debug SETSHADERRESOURCES_HAZARD D3D11 warnings - for (unsigned int vertexSerialIndex = 0; vertexSerialIndex < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; vertexSerialIndex++) - { - if (colorbuffer->getTextureSerial() != 0 && mCurVertexTextureSerials[vertexSerialIndex] == colorbuffer->getTextureSerial()) - { - setTexture(gl::SAMPLER_VERTEX, vertexSerialIndex, NULL); - } - } - - for (unsigned int pixelSerialIndex = 0; pixelSerialIndex < gl::MAX_TEXTURE_IMAGE_UNITS; pixelSerialIndex++) - { - if (colorbuffer->getTextureSerial() != 0 && mCurPixelTextureSerials[pixelSerialIndex] == colorbuffer->getTextureSerial()) - { - setTexture(gl::SAMPLER_PIXEL, pixelSerialIndex, NULL); - } - } -#endif - } - } - - // Get the depth stencil render buffer and serials - gl::Renderbuffer *depthStencil = NULL; - unsigned int depthbufferSerial = 0; - unsigned int stencilbufferSerial = 0; - if (framebuffer->getDepthbufferType() != GL_NONE) - { - depthStencil = framebuffer->getDepthbuffer(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - SafeRelease(framebufferRTVs); - return false; - } - - depthbufferSerial = depthStencil->getSerial(); - } - else if (framebuffer->getStencilbufferType() != GL_NONE) - { - depthStencil = framebuffer->getStencilbuffer(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - SafeRelease(framebufferRTVs); - return false; - } - - stencilbufferSerial = depthStencil->getSerial(); - } - - // Extract the depth stencil sizes and view - unsigned int depthSize = 0; - unsigned int stencilSize = 0; - ID3D11DepthStencilView* framebufferDSV = NULL; - if (depthStencil) - { - RenderTarget11 *depthStencilRenderTarget = RenderTarget11::makeRenderTarget11(depthStencil->getDepthStencil()); - if (!depthStencilRenderTarget) - { - ERR("render target pointer unexpectedly null."); - SafeRelease(framebufferRTVs); - return false; - } - - framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); - if (!framebufferDSV) - { - ERR("depth stencil view pointer unexpectedly null."); - SafeRelease(framebufferRTVs); - return false; - } - - // If there is no render buffer, the width, height and format values come from - // the depth stencil - if (missingColorRenderTarget) - { - renderTargetWidth = depthStencil->getWidth(); - renderTargetHeight = depthStencil->getHeight(); - renderTargetFormat = depthStencil->getActualFormat(); - } - - depthSize = depthStencil->getDepthSize(); - stencilSize = depthStencil->getStencilSize(); - } - - // Apply the render target and depth stencil - if (!mRenderTargetDescInitialized || !mDepthStencilInitialized || - memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 || - depthbufferSerial != mAppliedDepthbufferSerial || - stencilbufferSerial != mAppliedStencilbufferSerial) - { - mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), framebufferRTVs, framebufferDSV); - - mRenderTargetDesc.width = renderTargetWidth; - mRenderTargetDesc.height = renderTargetHeight; - mRenderTargetDesc.format = renderTargetFormat; - mForceSetViewport = true; - mForceSetScissor = true; - - if (!mDepthStencilInitialized || depthSize != mCurDepthSize) - { - mCurDepthSize = depthSize; - mForceSetRasterState = true; - } - - mCurStencilSize = stencilSize; - - for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) - { - mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex]; - } - mAppliedDepthbufferSerial = depthbufferSerial; - mAppliedStencilbufferSerial = stencilbufferSerial; - mRenderTargetDescInitialized = true; - mDepthStencilInitialized = true; - } - - return true; -} - -GLenum Renderer11::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) -{ - TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; - GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances); - if (err != GL_NO_ERROR) - { - return err; - } - - return mInputLayoutCache.applyVertexBuffers(attributes, programBinary); -} - -GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) -{ - GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); - - if (err == GL_NO_ERROR) - { - if (indexInfo->storage) - { - if (indexInfo->serial != mAppliedStorageIBSerial || indexInfo->startOffset != mAppliedIBOffset) - { - BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage); - IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); - - mDeviceContext->IASetIndexBuffer(storage->getBuffer(BUFFER_USAGE_INDEX), indexBuffer->getIndexFormat(), indexInfo->startOffset); - - mAppliedIBSerial = 0; - mAppliedStorageIBSerial = storage->getSerial(); - mAppliedIBOffset = indexInfo->startOffset; - } - } - else if (indexInfo->serial != mAppliedIBSerial || indexInfo->startOffset != mAppliedIBOffset) - { - IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); - - mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset); - - mAppliedIBSerial = indexInfo->serial; - mAppliedStorageIBSerial = 0; - mAppliedIBOffset = indexInfo->startOffset; - } - } - - return err; -} - -void Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances) -{ - if (mode == GL_LINE_LOOP) - { - drawLineLoop(count, GL_NONE, NULL, 0, NULL); - } - else if (mode == GL_TRIANGLE_FAN) - { - drawTriangleFan(count, GL_NONE, NULL, 0, NULL, instances); - } - else if (instances > 0) - { - mDeviceContext->DrawInstanced(count, instances, 0, 0); - } - else - { - mDeviceContext->Draw(count, 0); - } -} - -void Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) -{ - if (mode == GL_LINE_LOOP) - { - drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); - } - else if (mode == GL_TRIANGLE_FAN) - { - drawTriangleFan(count, type, indices, indexInfo.minIndex, elementArrayBuffer, instances); - } - else if (instances > 0) - { - mDeviceContext->DrawIndexedInstanced(count, instances, 0, -static_cast(indexInfo.minIndex), 0); - } - else - { - mDeviceContext->DrawIndexed(count, 0, -static_cast(indexInfo.minIndex)); - } -} - -template -static void fillLineLoopIndices(GLenum type, GLsizei count, const GLvoid *indices, T *data) -{ - switch (type) - { - case GL_NONE: // Non-indexed draw - for (int i = 0; i < count; i++) - { - data[i] = i; - } - data[count] = 0; - break; - case GL_UNSIGNED_BYTE: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_SHORT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_INT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - default: UNREACHABLE(); - } -} - -template -static void fillTriangleFanIndices(GLenum type, unsigned int numTris, const GLvoid *indices, T *data) -{ - switch (type) - { - case GL_NONE: // Non-indexed draw - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = 0; - data[i*3 + 1] = i + 1; - data[i*3 + 2] = i + 2; - } - break; - case GL_UNSIGNED_BYTE: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - case GL_UNSIGNED_SHORT: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - case GL_UNSIGNED_INT: - for (unsigned int i = 0; i < numTris; i++) - { - data[i*3 + 0] = static_cast(indices)[0]; - data[i*3 + 1] = static_cast(indices)[i + 1]; - data[i*3 + 2] = static_cast(indices)[i + 2]; - } - break; - default: UNREACHABLE(); - } -} - -void Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) -{ - // Get the raw indices for an indexed draw - if (type != GL_NONE && elementArrayBuffer) - { - gl::Buffer *indexBuffer = elementArrayBuffer; - BufferStorage *storage = indexBuffer->getStorage(); - intptr_t offset = reinterpret_cast(indices); - indices = static_cast(storage->getData()) + offset; - } - - const int indexType = get32BitIndexSupport() ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; - - if (!mLineLoopIB) - { - mLineLoopIB = new StreamingIndexBufferInterface(this); - if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType)) - { - delete mLineLoopIB; - mLineLoopIB = NULL; - - ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - - // Checked by Renderer11::applyPrimitiveType - ASSERT(count >= 0); - - if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) - { - ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); - return gl::error(GL_OUT_OF_MEMORY); - } - - const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); - if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, indexType)) - { - ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - - void* mappedMemory = NULL; - unsigned int offset; - if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) - { - ERR("Could not map index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - - if (indexType == GL_UNSIGNED_SHORT) - fillLineLoopIndices(type, count, indices, reinterpret_cast(mappedMemory)); - else - fillLineLoopIndices(type, count, indices, reinterpret_cast(mappedMemory)); - unsigned int indexBufferOffset = offset; - - if (!mLineLoopIB->unmapBuffer()) - { - ERR("Could not unmap index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - - if (mAppliedIBSerial != mLineLoopIB->getSerial() || mAppliedIBOffset != indexBufferOffset) - { - IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mLineLoopIB->getIndexBuffer()); - - mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); - mAppliedIBSerial = mLineLoopIB->getSerial(); - mAppliedStorageIBSerial = 0; - mAppliedIBOffset = indexBufferOffset; - } - - mDeviceContext->DrawIndexed(count + 1, 0, -minIndex); -} - -void Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances) -{ - // Get the raw indices for an indexed draw - if (type != GL_NONE && elementArrayBuffer) - { - gl::Buffer *indexBuffer = elementArrayBuffer; - BufferStorage *storage = indexBuffer->getStorage(); - intptr_t offset = reinterpret_cast(indices); - indices = static_cast(storage->getData()) + offset; - } - - const int indexType = get32BitIndexSupport() ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT; - - if (!mTriangleFanIB) - { - mTriangleFanIB = new StreamingIndexBufferInterface(this); - if (!mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType)) - { - delete mTriangleFanIB; - mTriangleFanIB = NULL; - - ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - - // Checked by Renderer11::applyPrimitiveType - ASSERT(count >= 3); - - const unsigned int numTris = count - 2; - - if (numTris > (std::numeric_limits::max() / (sizeof(unsigned int) * 3))) - { - ERR("Could not create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required."); - return gl::error(GL_OUT_OF_MEMORY); - } - - const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int); - if (!mTriangleFanIB->reserveBufferSpace(spaceNeeded, indexType)) - { - ERR("Could not reserve enough space in scratch index buffer for GL_TRIANGLE_FAN."); - return gl::error(GL_OUT_OF_MEMORY); - } - - void* mappedMemory = NULL; - unsigned int offset; - if (!mTriangleFanIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) - { - ERR("Could not map scratch index buffer for GL_TRIANGLE_FAN."); - return gl::error(GL_OUT_OF_MEMORY); - } - - if (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()) - { - ERR("Could not unmap scratch index buffer for GL_TRIANGLE_FAN."); - return gl::error(GL_OUT_OF_MEMORY); - } - - if (mAppliedIBSerial != mTriangleFanIB->getSerial() || mAppliedIBOffset != indexBufferOffset) - { - IndexBuffer11 *indexBuffer = IndexBuffer11::makeIndexBuffer11(mTriangleFanIB->getIndexBuffer()); - - mDeviceContext->IASetIndexBuffer(indexBuffer->getBuffer(), indexBuffer->getIndexFormat(), indexBufferOffset); - mAppliedIBSerial = mTriangleFanIB->getSerial(); - mAppliedStorageIBSerial = 0; - mAppliedIBOffset = indexBufferOffset; - } - - if (instances > 0) - { - mDeviceContext->DrawIndexedInstanced(numTris * 3, instances, 0, -minIndex, 0); - } - else - { - mDeviceContext->DrawIndexed(numTris * 3, 0, -minIndex); - } -} - -void Renderer11::applyShaders(gl::ProgramBinary *programBinary) -{ - unsigned int programBinarySerial = programBinary->getSerial(); - const bool updateProgramState = (programBinarySerial != mAppliedProgramBinarySerial); - - if (updateProgramState) - { - ShaderExecutable *vertexExe = programBinary->getVertexExecutable(); - ShaderExecutable *pixelExe = programBinary->getPixelExecutable(); - - ID3D11VertexShader *vertexShader = NULL; - if (vertexExe) vertexShader = ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader(); - - ID3D11PixelShader *pixelShader = NULL; - if (pixelExe) pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader(); - - mDeviceContext->PSSetShader(pixelShader, NULL, 0); - mDeviceContext->VSSetShader(vertexShader, NULL, 0); - - programBinary->dirtyAllUniforms(); - - mAppliedProgramBinarySerial = programBinarySerial; - } - - // Only use the geometry shader currently for point sprite drawing - const bool usesGeometryShader = (programBinary->usesGeometryShader() && mCurRasterState.pointDrawMode); - - if (updateProgramState || usesGeometryShader != mIsGeometryShaderActive) - { - if (usesGeometryShader) - { - ShaderExecutable *geometryExe = programBinary->getGeometryExecutable(); - ID3D11GeometryShader *geometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader(); - mDeviceContext->GSSetShader(geometryShader, NULL, 0); - } - else - { - mDeviceContext->GSSetShader(NULL, NULL, 0); - } - - mIsGeometryShaderActive = usesGeometryShader; - } -} - -void Renderer11::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) -{ - ShaderExecutable11 *vertexExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getVertexExecutable()); - ShaderExecutable11 *pixelExecutable = ShaderExecutable11::makeShaderExecutable11(programBinary->getPixelExecutable()); - - unsigned int totalRegisterCountVS = 0; - unsigned int totalRegisterCountPS = 0; - - bool vertexUniformsDirty = false; - bool pixelUniformsDirty = false; - - for (gl::UniformArray::const_iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++) - { - const gl::Uniform *uniform = *uniform_iterator; - - if (uniform->vsRegisterIndex >= 0) - { - totalRegisterCountVS += uniform->registerCount; - vertexUniformsDirty = vertexUniformsDirty || uniform->dirty; - } - - if (uniform->psRegisterIndex >= 0) - { - totalRegisterCountPS += uniform->registerCount; - pixelUniformsDirty = pixelUniformsDirty || uniform->dirty; - } - } - - ID3D11Buffer *vertexConstantBuffer = vertexExecutable->getConstantBuffer(mDevice, totalRegisterCountVS); - ID3D11Buffer *pixelConstantBuffer = pixelExecutable->getConstantBuffer(mDevice, totalRegisterCountPS); - - float (*mapVS)[4] = NULL; - float (*mapPS)[4] = NULL; - - if (totalRegisterCountVS > 0 && vertexUniformsDirty) - { - D3D11_MAPPED_SUBRESOURCE map = {0}; - HRESULT result = mDeviceContext->Map(vertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); - ASSERT(SUCCEEDED(result)); - mapVS = (float(*)[4])map.pData; - } - - if (totalRegisterCountPS > 0 && pixelUniformsDirty) - { - D3D11_MAPPED_SUBRESOURCE map = {0}; - HRESULT result = mDeviceContext->Map(pixelConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &map); - ASSERT(SUCCEEDED(result)); - mapPS = (float(*)[4])map.pData; - } - - for (gl::UniformArray::iterator uniform_iterator = uniformArray->begin(); uniform_iterator != uniformArray->end(); uniform_iterator++) - { - gl::Uniform *uniform = *uniform_iterator; - - if (uniform->type != GL_SAMPLER_2D && uniform->type != GL_SAMPLER_CUBE) - { - if (uniform->vsRegisterIndex >= 0 && mapVS) - { - memcpy(mapVS + uniform->vsRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4])); - } - - if (uniform->psRegisterIndex >= 0 && mapPS) - { - memcpy(mapPS + uniform->psRegisterIndex, uniform->data, uniform->registerCount * sizeof(float[4])); - } - } - - uniform->dirty = false; - } - - if (mapVS) - { - mDeviceContext->Unmap(vertexConstantBuffer, 0); - } - - if (mapPS) - { - mDeviceContext->Unmap(pixelConstantBuffer, 0); - } - - if (mCurrentVertexConstantBuffer != vertexConstantBuffer) - { - mDeviceContext->VSSetConstantBuffers(0, 1, &vertexConstantBuffer); - mCurrentVertexConstantBuffer = vertexConstantBuffer; - } - - if (mCurrentPixelConstantBuffer != pixelConstantBuffer) - { - mDeviceContext->PSSetConstantBuffers(0, 1, &pixelConstantBuffer); - mCurrentPixelConstantBuffer = pixelConstantBuffer; - } - - // Driver uniforms - if (!mDriverConstantBufferVS) - { - D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = sizeof(dx_VertexConstants); - constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; - constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - constantBufferDescription.CPUAccessFlags = 0; - constantBufferDescription.MiscFlags = 0; - constantBufferDescription.StructureByteStride = 0; - - HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferVS); - ASSERT(SUCCEEDED(result)); - - mDeviceContext->VSSetConstantBuffers(1, 1, &mDriverConstantBufferVS); - } - - if (!mDriverConstantBufferPS) - { - D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = sizeof(dx_PixelConstants); - constantBufferDescription.Usage = D3D11_USAGE_DEFAULT; - constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - constantBufferDescription.CPUAccessFlags = 0; - constantBufferDescription.MiscFlags = 0; - constantBufferDescription.StructureByteStride = 0; - - HRESULT result = mDevice->CreateBuffer(&constantBufferDescription, NULL, &mDriverConstantBufferPS); - ASSERT(SUCCEEDED(result)); - - mDeviceContext->PSSetConstantBuffers(1, 1, &mDriverConstantBufferPS); - } - - if (memcmp(&mVertexConstants, &mAppliedVertexConstants, sizeof(dx_VertexConstants)) != 0) - { - mDeviceContext->UpdateSubresource(mDriverConstantBufferVS, 0, NULL, &mVertexConstants, 16, 0); - memcpy(&mAppliedVertexConstants, &mVertexConstants, sizeof(dx_VertexConstants)); - } - - if (memcmp(&mPixelConstants, &mAppliedPixelConstants, sizeof(dx_PixelConstants)) != 0) - { - mDeviceContext->UpdateSubresource(mDriverConstantBufferPS, 0, NULL, &mPixelConstants, 16, 0); - memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants)); - } - - // needed for the point sprite geometry shader - if (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0 && mCurrentGeometryConstantBuffer != mDriverConstantBufferPS) - { - mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS); - mCurrentGeometryConstantBuffer = mDriverConstantBufferPS; - } -} - -void Renderer11::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) -{ - gl::Renderbuffer *firstRenderbuffer = frameBuffer->getFirstColorbuffer(); - GLenum internalFormat = firstRenderbuffer ? firstRenderbuffer->getInternalFormat() : GL_NONE; - - bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) && - ((!clearParams.colorMaskRed && gl::GetRedSize(internalFormat) > 0) || - (!clearParams.colorMaskGreen && gl::GetGreenSize(internalFormat) > 0) || - (!clearParams.colorMaskBlue && gl::GetBlueSize(internalFormat) > 0) || - (!clearParams.colorMaskAlpha && gl::GetAlphaSize(internalFormat) > 0)); - - unsigned int stencilUnmasked = 0x0; - if (frameBuffer->hasStencil()) - { - unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat()); - stencilUnmasked = (0x1 << stencilSize) - 1; - } - bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) && - (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; - - bool needScissoredClear = mScissorEnabled && (mCurScissor.x > 0 || mCurScissor.y > 0 || - mCurScissor.x + mCurScissor.width < mRenderTargetDesc.width || - mCurScissor.y + mCurScissor.height < mRenderTargetDesc.height); - - if (needMaskedColorClear || needMaskedStencilClear || needScissoredClear) - { - maskedClear(clearParams, frameBuffer); - } - else - { - if (clearParams.mask & GL_COLOR_BUFFER_BIT) - { - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - if (frameBuffer->isEnabledColorAttachment(colorAttachment)) - { - gl::Renderbuffer *renderbufferObject = frameBuffer->getColorbuffer(colorAttachment); - if (renderbufferObject) - { - RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getRenderTarget()); - if (!renderTarget) - { - ERR("render target pointer unexpectedly null."); - return; - } - - ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView(); - if (!framebufferRTV) - { - ERR("render target view pointer unexpectedly null."); - return; - } - - GLenum format = renderbufferObject->getInternalFormat(); - - const float clearValues[4] = { (gl::GetRedSize(format) > 0) ? clearParams.colorClearValue.red : 0.0f, - (gl::GetGreenSize(format) > 0) ? clearParams.colorClearValue.green : 0.0f, - (gl::GetBlueSize(format) > 0) ? clearParams.colorClearValue.blue : 0.0f, - (gl::GetAlphaSize(format) > 0) ? clearParams.colorClearValue.alpha : 1.0f }; - mDeviceContext->ClearRenderTargetView(framebufferRTV, clearValues); - } - } - } - } - if (clearParams.mask & GL_DEPTH_BUFFER_BIT || clearParams.mask & GL_STENCIL_BUFFER_BIT) - { - gl::Renderbuffer *renderbufferObject = frameBuffer->getDepthOrStencilbuffer(); - if (renderbufferObject) - { - RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(renderbufferObject->getDepthStencil()); - if (!renderTarget) - { - ERR("render target pointer unexpectedly null."); - return; - } - - ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView(); - if (!framebufferDSV) - { - ERR("depth stencil view pointer unexpectedly null."); - return; - } - - UINT clearFlags = 0; - if (clearParams.mask & GL_DEPTH_BUFFER_BIT) - { - clearFlags |= D3D11_CLEAR_DEPTH; - } - if (clearParams.mask & GL_STENCIL_BUFFER_BIT) - { - clearFlags |= D3D11_CLEAR_STENCIL; - } - - float depthClear = gl::clamp01(clearParams.depthClearValue); - UINT8 stencilClear = clearParams.stencilClearValue & 0x000000FF; - - mDeviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear); - } - } - } -} - -void Renderer11::maskedClear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) -{ - HRESULT result; - - if (!mClearResourcesInitialized) - { - ASSERT(!mClearVB && !mClearVS && !mClearSinglePS && !mClearMultiplePS && !mClearScissorRS && !mClearNoScissorRS); - - D3D11_BUFFER_DESC vbDesc; - vbDesc.ByteWidth = sizeof(d3d11::PositionDepthColorVertex) * 4; - vbDesc.Usage = D3D11_USAGE_DYNAMIC; - vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - vbDesc.MiscFlags = 0; - vbDesc.StructureByteStride = 0; - - result = mDevice->CreateBuffer(&vbDesc, NULL, &mClearVB); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearVB, "Renderer11 masked clear vertex buffer"); - - D3D11_INPUT_ELEMENT_DESC quadLayout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - - result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Clear, sizeof(g_VS_Clear), &mClearIL); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearIL, "Renderer11 masked clear input layout"); - - result = mDevice->CreateVertexShader(g_VS_Clear, sizeof(g_VS_Clear), NULL, &mClearVS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearVS, "Renderer11 masked clear vertex shader"); - - result = mDevice->CreatePixelShader(g_PS_ClearSingle, sizeof(g_PS_ClearSingle), NULL, &mClearSinglePS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearSinglePS, "Renderer11 masked clear pixel shader (1 RT)"); - - result = mDevice->CreatePixelShader(g_PS_ClearMultiple, sizeof(g_PS_ClearMultiple), NULL, &mClearMultiplePS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearMultiplePS, "Renderer11 masked clear pixel shader (MRT)"); - - D3D11_RASTERIZER_DESC rsScissorDesc; - rsScissorDesc.FillMode = D3D11_FILL_SOLID; - rsScissorDesc.CullMode = D3D11_CULL_NONE; - rsScissorDesc.FrontCounterClockwise = FALSE; - rsScissorDesc.DepthBias = 0; - rsScissorDesc.DepthBiasClamp = 0.0f; - rsScissorDesc.SlopeScaledDepthBias = 0.0f; - rsScissorDesc.DepthClipEnable = FALSE; - rsScissorDesc.ScissorEnable = TRUE; - rsScissorDesc.MultisampleEnable = FALSE; - rsScissorDesc.AntialiasedLineEnable = FALSE; - - result = mDevice->CreateRasterizerState(&rsScissorDesc, &mClearScissorRS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearScissorRS, "Renderer11 masked clear scissor rasterizer state"); - - D3D11_RASTERIZER_DESC rsNoScissorDesc; - rsNoScissorDesc.FillMode = D3D11_FILL_SOLID; - rsNoScissorDesc.CullMode = D3D11_CULL_NONE; - rsNoScissorDesc.FrontCounterClockwise = FALSE; - rsNoScissorDesc.DepthBias = 0; - rsNoScissorDesc.DepthBiasClamp = 0.0f; - rsNoScissorDesc.SlopeScaledDepthBias = 0.0f; - rsNoScissorDesc.DepthClipEnable = FALSE; - rsNoScissorDesc.ScissorEnable = FALSE; - rsNoScissorDesc.MultisampleEnable = FALSE; - rsNoScissorDesc.AntialiasedLineEnable = FALSE; - - result = mDevice->CreateRasterizerState(&rsNoScissorDesc, &mClearNoScissorRS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mClearNoScissorRS, "Renderer11 masked clear no scissor rasterizer state"); - - mClearResourcesInitialized = true; - } - - // Prepare the depth stencil state to write depth values if the depth should be cleared - // and stencil values if the stencil should be cleared - gl::DepthStencilState glDSState; - glDSState.depthTest = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0; - glDSState.depthFunc = GL_ALWAYS; - glDSState.depthMask = (clearParams.mask & GL_DEPTH_BUFFER_BIT) != 0; - glDSState.stencilTest = (clearParams.mask & GL_STENCIL_BUFFER_BIT) != 0; - glDSState.stencilFunc = GL_ALWAYS; - glDSState.stencilMask = 0; - glDSState.stencilFail = GL_REPLACE; - glDSState.stencilPassDepthFail = GL_REPLACE; - glDSState.stencilPassDepthPass = GL_REPLACE; - glDSState.stencilWritemask = clearParams.stencilWriteMask; - glDSState.stencilBackFunc = GL_ALWAYS; - glDSState.stencilBackMask = 0; - glDSState.stencilBackFail = GL_REPLACE; - glDSState.stencilBackPassDepthFail = GL_REPLACE; - glDSState.stencilBackPassDepthPass = GL_REPLACE; - glDSState.stencilBackWritemask = clearParams.stencilWriteMask; - - int stencilClear = clearParams.stencilClearValue & 0x000000FF; - - ID3D11DepthStencilState *dsState = mStateCache.getDepthStencilState(glDSState); - - // Prepare the blend state to use a write mask if the color buffer should be cleared - gl::BlendState glBlendState; - glBlendState.blend = false; - glBlendState.sourceBlendRGB = GL_ONE; - glBlendState.destBlendRGB = GL_ZERO; - glBlendState.sourceBlendAlpha = GL_ONE; - glBlendState.destBlendAlpha = GL_ZERO; - glBlendState.blendEquationRGB = GL_FUNC_ADD; - glBlendState.blendEquationAlpha = GL_FUNC_ADD; - glBlendState.colorMaskRed = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskRed : false; - glBlendState.colorMaskGreen = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskGreen : false; - glBlendState.colorMaskBlue = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskBlue : false; - glBlendState.colorMaskAlpha = (clearParams.mask & GL_COLOR_BUFFER_BIT) ? clearParams.colorMaskAlpha : false; - glBlendState.sampleAlphaToCoverage = false; - glBlendState.dither = false; - - static const float blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; - static const UINT sampleMask = 0xFFFFFFFF; - - ID3D11BlendState *blendState = mStateCache.getBlendState(frameBuffer, glBlendState); - - // Set the vertices - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = mDeviceContext->Map(mClearVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Failed to map masked clear vertex buffer, HRESULT: 0x%X.", result); - return; - } - - d3d11::PositionDepthColorVertex *vertices = reinterpret_cast(mappedResource.pData); - - float depthClear = gl::clamp01(clearParams.depthClearValue); - d3d11::SetPositionDepthColorVertex(&vertices[0], -1.0f, 1.0f, depthClear, clearParams.colorClearValue); - d3d11::SetPositionDepthColorVertex(&vertices[1], -1.0f, -1.0f, depthClear, clearParams.colorClearValue); - d3d11::SetPositionDepthColorVertex(&vertices[2], 1.0f, 1.0f, depthClear, clearParams.colorClearValue); - d3d11::SetPositionDepthColorVertex(&vertices[3], 1.0f, -1.0f, depthClear, clearParams.colorClearValue); - - mDeviceContext->Unmap(mClearVB, 0); - - // Apply state - mDeviceContext->OMSetBlendState(blendState, blendFactors, sampleMask); - mDeviceContext->OMSetDepthStencilState(dsState, stencilClear); - mDeviceContext->RSSetState(mScissorEnabled ? mClearScissorRS : mClearNoScissorRS); - - // Apply shaders - ID3D11PixelShader *pixelShader = frameBuffer->usingExtendedDrawBuffers() ? mClearMultiplePS : mClearSinglePS; - - mDeviceContext->IASetInputLayout(mClearIL); - mDeviceContext->VSSetShader(mClearVS, NULL, 0); - mDeviceContext->PSSetShader(pixelShader, NULL, 0); - mDeviceContext->GSSetShader(NULL, NULL, 0); - - // Apply vertex buffer - static UINT stride = sizeof(d3d11::PositionDepthColorVertex); - static UINT startIdx = 0; - mDeviceContext->IASetVertexBuffers(0, 1, &mClearVB, &stride, &startIdx); - mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - - // Draw the clear quad - mDeviceContext->Draw(4, 0); - - // Clean up - markAllStateDirty(); -} - -void Renderer11::markAllStateDirty() -{ - for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) - { - mAppliedRenderTargetSerials[rtIndex] = 0; - } - mAppliedDepthbufferSerial = 0; - mAppliedStencilbufferSerial = 0; - mDepthStencilInitialized = false; - mRenderTargetDescInitialized = false; - - for (int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) - { - mForceSetVertexSamplerStates[i] = true; - mCurVertexTextureSerials[i] = 0; - } - for (int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++) - { - mForceSetPixelSamplerStates[i] = true; - mCurPixelTextureSerials[i] = 0; - } - - mForceSetBlendState = true; - mForceSetRasterState = true; - mForceSetDepthStencilState = true; - mForceSetScissor = true; - mForceSetViewport = true; - - mAppliedIBSerial = 0; - mAppliedStorageIBSerial = 0; - mAppliedIBOffset = 0; - - mAppliedProgramBinarySerial = 0; - memset(&mAppliedVertexConstants, 0, sizeof(dx_VertexConstants)); - memset(&mAppliedPixelConstants, 0, sizeof(dx_PixelConstants)); - - mInputLayoutCache.markDirty(); - - mCurrentVertexConstantBuffer = NULL; - mCurrentPixelConstantBuffer = NULL; - mCurrentGeometryConstantBuffer = NULL; - - mCurrentPrimitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED; -} - -void Renderer11::releaseDeviceResources() -{ - mStateCache.clear(); - mInputLayoutCache.clear(); - - delete mVertexDataManager; - mVertexDataManager = NULL; - - delete mIndexDataManager; - mIndexDataManager = NULL; - - delete mLineLoopIB; - mLineLoopIB = NULL; - - delete mTriangleFanIB; - mTriangleFanIB = NULL; - - SafeRelease(mCopyVB); - SafeRelease(mCopySampler); - SafeRelease(mCopyIL); - SafeRelease(mCopyIL); - SafeRelease(mCopyVS); - SafeRelease(mCopyRGBAPS); - SafeRelease(mCopyRGBPS); - SafeRelease(mCopyLumPS); - SafeRelease(mCopyLumAlphaPS); - - mCopyResourcesInitialized = false; - - SafeRelease(mClearVB); - SafeRelease(mClearIL); - SafeRelease(mClearVS); - SafeRelease(mClearSinglePS); - SafeRelease(mClearMultiplePS); - SafeRelease(mClearScissorRS); - SafeRelease(mClearNoScissorRS); - - mClearResourcesInitialized = false; - - SafeRelease(mDriverConstantBufferVS); - SafeRelease(mDriverConstantBufferPS); - SafeRelease(mSyncQuery); -} - -void Renderer11::notifyDeviceLost() -{ - mDeviceLost = true; - mDisplay->notifyDeviceLost(); -} - -bool Renderer11::isDeviceLost() -{ - return mDeviceLost; -} - -// set notify to true to broadcast a message to all contexts of the device loss -bool Renderer11::testDeviceLost(bool notify) -{ - bool isLost = false; - - // GetRemovedReason is used to test if the device is removed - HRESULT result = mDevice->GetDeviceRemovedReason(); - isLost = d3d11::isDeviceLostError(result); - - if (isLost) - { - // Log error if this is a new device lost event - if (mDeviceLost == false) - { - ERR("The D3D11 device was removed: 0x%08X", result); - } - - // ensure we note the device loss -- - // we'll probably get this done again by notifyDeviceLost - // but best to remember it! - // Note that we don't want to clear the device loss status here - // -- this needs to be done by resetDevice - mDeviceLost = true; - if (notify) - { - notifyDeviceLost(); - } - } - - return isLost; -} - -bool Renderer11::testDeviceResettable() -{ - // determine if the device is resettable by creating a dummy device - PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice"); - - if (D3D11CreateDevice == NULL) - { - return false; - } - - D3D_FEATURE_LEVEL featureLevels[] = - { - D3D_FEATURE_LEVEL_11_0, - D3D_FEATURE_LEVEL_10_1, - D3D_FEATURE_LEVEL_10_0, -#if !defined(ANGLE_ENABLE_D3D9) - D3D_FEATURE_LEVEL_9_3, - D3D_FEATURE_LEVEL_9_2, - D3D_FEATURE_LEVEL_9_1, -#endif - }; - - ID3D11Device* dummyDevice; - D3D_FEATURE_LEVEL dummyFeatureLevel; - ID3D11DeviceContext* dummyContext; - - HRESULT result = D3D11CreateDevice(NULL, - D3D_DRIVER_TYPE_HARDWARE, - NULL, - #if defined(_DEBUG) - D3D11_CREATE_DEVICE_DEBUG, - #else - 0, - #endif - featureLevels, - ArraySize(featureLevels), - D3D11_SDK_VERSION, - &dummyDevice, - &dummyFeatureLevel, - &dummyContext); - - if (!mDevice || FAILED(result)) - { - return false; - } - - dummyContext->Release(); - dummyDevice->Release(); - - return true; -} - -void Renderer11::release() -{ - releaseDeviceResources(); - - if (mDxgiFactory) - { - mDxgiFactory->Release(); - mDxgiFactory = NULL; - } - - if (mDxgiAdapter) - { - mDxgiAdapter->Release(); - mDxgiAdapter = NULL; - } - - if (mDeviceContext) - { - mDeviceContext->ClearState(); - mDeviceContext->Flush(); - mDeviceContext->Release(); - mDeviceContext = NULL; - } - - if (mDevice) - { - mDevice->Release(); - mDevice = NULL; - } - - if (mD3d11Module) - { - FreeLibrary(mD3d11Module); - mD3d11Module = NULL; - } - - if (mDxgiModule) - { - FreeLibrary(mDxgiModule); - mDxgiModule = NULL; - } -} - -bool Renderer11::resetDevice() -{ - // recreate everything - release(); - EGLint result = initialize(); - - if (result != EGL_SUCCESS) - { - ERR("Could not reinitialize D3D11 device: %08X", result); - return false; - } - - mDeviceLost = false; - - return true; -} - -DWORD Renderer11::getAdapterVendor() const -{ - return mAdapterDescription.VendorId; -} - -std::string Renderer11::getRendererDescription() const -{ - std::ostringstream rendererString; - - rendererString << mDescription; - rendererString << " Direct3D11"; - - rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel(); - rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel(); - - return rendererString.str(); -} - -GUID Renderer11::getAdapterIdentifier() const -{ - // Use the adapter LUID as our adapter ID - // This number is local to a machine is only guaranteed to be unique between restarts - META_ASSERT(sizeof(LUID) <= sizeof(GUID)); - GUID adapterId = {0}; - memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID)); - return adapterId; -} - -bool Renderer11::getBGRATextureSupport() const -{ - return mBGRATextureSupport; -} - -bool Renderer11::getDXT1TextureSupport() -{ - return mDXT1TextureSupport; -} - -bool Renderer11::getDXT3TextureSupport() -{ - return mDXT3TextureSupport; -} - -bool Renderer11::getDXT5TextureSupport() -{ - return mDXT5TextureSupport; -} - -bool Renderer11::getDepthTextureSupport() const -{ - return mDepthTextureSupport; -} - -bool Renderer11::getFloat32TextureSupport(bool *filtering, bool *renderable) -{ - *renderable = mFloat32RenderSupport; - *filtering = mFloat32FilterSupport; - return mFloat32TextureSupport; -} - -bool Renderer11::getFloat16TextureSupport(bool *filtering, bool *renderable) -{ - *renderable = mFloat16RenderSupport; - *filtering = mFloat16FilterSupport; - return mFloat16TextureSupport; -} - -bool Renderer11::getLuminanceTextureSupport() -{ - return false; -} - -bool Renderer11::getLuminanceAlphaTextureSupport() -{ - return false; -} - -bool Renderer11::getTextureFilterAnisotropySupport() const -{ - return true; -} - -float Renderer11::getTextureMaxAnisotropy() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - return D3D11_MAX_MAXANISOTROPY; - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return D3D10_MAX_MAXANISOTROPY; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - return 16; - case D3D_FEATURE_LEVEL_9_1: - return D3D_FL9_1_DEFAULT_MAX_ANISOTROPY; - default: UNREACHABLE(); - return 0; - } -} - -bool Renderer11::getEventQuerySupport() -{ - return true; -} - -Range Renderer11::getViewportBounds() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - return Range(D3D11_VIEWPORT_BOUNDS_MIN, D3D11_VIEWPORT_BOUNDS_MAX); - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return Range(D3D10_VIEWPORT_BOUNDS_MIN, D3D10_VIEWPORT_BOUNDS_MAX); - case D3D_FEATURE_LEVEL_9_3: - return Range(D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION * -2, D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2); - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return Range(D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION * -2, D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2); - default: UNREACHABLE(); - return Range(0, 0); - } -} - -unsigned int Renderer11::getMaxVertexTextureImageUnits() const -{ - META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM4 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return MAX_TEXTURE_IMAGE_UNITS_VTF_SM4; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return 0; - default: UNREACHABLE(); - return 0; - } -} - -unsigned int Renderer11::getMaxCombinedTextureImageUnits() const -{ - return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits(); -} - -unsigned int Renderer11::getReservedVertexUniformVectors() const -{ - return 0; // Driver uniforms are stored in a separate constant buffer -} - -unsigned int Renderer11::getReservedFragmentUniformVectors() const -{ - return 0; // Driver uniforms are stored in a separate constant buffer -} - -unsigned int Renderer11::getMaxVertexUniformVectors() const -{ - META_ASSERT(MAX_VERTEX_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); - ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1); - return MAX_VERTEX_UNIFORM_VECTORS_D3D11; -} - -unsigned int Renderer11::getMaxFragmentUniformVectors() const -{ - META_ASSERT(MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 <= D3D10_REQ_CONSTANT_BUFFER_ELEMENT_COUNT); - ASSERT(mFeatureLevel >= D3D_FEATURE_LEVEL_9_1); - return MAX_FRAGMENT_UNIFORM_VECTORS_D3D11; -} - -unsigned int Renderer11::getMaxVaryingVectors() const -{ - META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT); - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - return D3D11_VS_OUTPUT_REGISTER_COUNT; - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return D3D10_VS_OUTPUT_REGISTER_COUNT; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return 8; - default: UNREACHABLE(); - return 0; - } -} - -bool Renderer11::getNonPower2TextureSupport() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return true; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return false; - default: UNREACHABLE(); - return false; - } -} - -bool Renderer11::getOcclusionQuerySupport() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return true; - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - return true; - case D3D_FEATURE_LEVEL_9_1: - return false; - default: UNREACHABLE(); - return false; - } -} - -bool Renderer11::getInstancingSupport() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - case D3D_FEATURE_LEVEL_9_3: - return true; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return false; - default: UNREACHABLE(); - return false; - } -} - -bool Renderer11::getShareHandleSupport() const -{ - // We only currently support share handles with BGRA surfaces, because - // chrome needs BGRA. Once chrome fixes this, we should always support them. - // PIX doesn't seem to support using share handles, so disable them. - return getBGRATextureSupport() && !gl::perfActive(); -} - -bool Renderer11::getDerivativeInstructionSupport() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return true; - case D3D_FEATURE_LEVEL_9_3: - return true; - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return false; - default: UNREACHABLE(); - return false; - } -} - -bool Renderer11::getPostSubBufferSupport() const -{ - // D3D11 does not support present with dirty rectangles until D3D11.1 and DXGI 1.2. - return false; -} - -int Renderer11::getMajorShaderModel() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5 - case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4 - case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4 - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MAJOR_VERSION; // 4 (level 9) - default: UNREACHABLE(); return 0; - } -} - -int Renderer11::getMinorShaderModel() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0 - case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1 - case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0 - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MINOR_VERSION; // 0 (level 9) - default: UNREACHABLE(); return 0; - } -} - -float Renderer11::getMaxPointSize() const -{ - // choose a reasonable maximum. we enforce this in the shader. - // (nb: on a Radeon 2600xt, DX9 reports a 256 max point size) - return 1024.0f; -} - -int Renderer11::getMaxViewportDimension() const -{ - // Maximum viewport size must be at least as large as the largest render buffer (or larger). - // In our case return the maximum texture size, which is the maximum render buffer size. - META_ASSERT(D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D11_VIEWPORT_BOUNDS_MAX); - META_ASSERT(D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION * 2 - 1 <= D3D10_VIEWPORT_BOUNDS_MAX); - - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 - case D3D_FEATURE_LEVEL_9_3: - return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: - return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 - default: UNREACHABLE(); - return 0; - } -} - -int Renderer11::getMaxTextureWidth() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 - case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 - default: UNREACHABLE(); return 0; - } -} - -int Renderer11::getMaxTextureHeight() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 16384 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 8192 - case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 4096 - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION; // 2048 - default: UNREACHABLE(); return 0; - } -} - -bool Renderer11::get32BitIndexSupport() const -{ - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: return D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP >= 32; // true - case D3D_FEATURE_LEVEL_9_3: - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: return false; - default: UNREACHABLE(); return false; - } -} - -int Renderer11::getMinSwapInterval() const -{ - return 0; -} - -int Renderer11::getMaxSwapInterval() const -{ - return 4; -} - -int Renderer11::getMaxSupportedSamples() const -{ - return mMaxSupportedSamples; -} - -int Renderer11::getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const -{ - if (requested == 0) - { - return 0; - } - - MultisampleSupportMap::const_iterator iter = mMultisampleSupportMap.find(format); - if (iter != mMultisampleSupportMap.end()) - { - const MultisampleSupportInfo& info = iter->second; - for (unsigned int i = requested - 1; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++) - { - if (info.qualityLevels[i] > 0) - { - return i + 1; - } - } - } - - return -1; -} - -unsigned int Renderer11::getMaxRenderTargets() const -{ - META_ASSERT(D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); - META_ASSERT(D3D10_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); - META_ASSERT(D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); - META_ASSERT(D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT <= gl::IMPLEMENTATION_MAX_DRAW_BUFFERS); - - switch (mFeatureLevel) - { - case D3D_FEATURE_LEVEL_11_0: - return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; // 8 - case D3D_FEATURE_LEVEL_10_1: - case D3D_FEATURE_LEVEL_10_0: - case D3D_FEATURE_LEVEL_9_3: // return D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT; // 4 - case D3D_FEATURE_LEVEL_9_2: - case D3D_FEATURE_LEVEL_9_1: // return D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT; // 1 - // Feature level 10.0 and 10.1 cards perform very poorly when the pixel shader - // outputs to multiple RTs that are not bound. - // TODO: Remove pixel shader outputs for render targets that are not bound. - return 1; - default: - UNREACHABLE(); - return 1; - } -} - -bool Renderer11::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) -{ - if (source && dest) - { - TextureStorage11_2D *source11 = TextureStorage11_2D::makeTextureStorage11_2D(source->getStorageInstance()); - TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(dest->getStorageInstance()); - - mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture()); - return true; - } - - return false; -} - -bool Renderer11::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) -{ - if (source && dest) - { - TextureStorage11_Cube *source11 = TextureStorage11_Cube::makeTextureStorage11_Cube(source->getStorageInstance()); - TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(dest->getStorageInstance()); - - mDeviceContext->CopyResource(dest11->getBaseTexture(), source11->getBaseTexture()); - return true; - } - - return false; -} - -bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) -{ - gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); - if (!colorbuffer) - { - ERR("Failed to retrieve the color buffer from the frame buffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); - if (!sourceRenderTarget) - { - ERR("Failed to retrieve the render target from the frame buffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - if (!source) - { - ERR("Failed to retrieve the render target view from the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - TextureStorage11_2D *storage11 = TextureStorage11_2D::makeTextureStorage11_2D(storage->getStorageInstance()); - if (!storage11) - { - ERR("Failed to retrieve the texture storage from the destination."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(level)); - if (!destRenderTarget) - { - ERR("Failed to retrieve the render target from the destination storage."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); - if (!dest) - { - ERR("Failed to retrieve the render target view from the destination render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - gl::Rectangle destRect; - destRect.x = xoffset; - destRect.y = yoffset; - destRect.width = sourceRect.width; - destRect.height = sourceRect.height; - - bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), - dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat); - - return ret; -} - -bool Renderer11::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) -{ - gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); - if (!colorbuffer) - { - ERR("Failed to retrieve the color buffer from the frame buffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); - if (!sourceRenderTarget) - { - ERR("Failed to retrieve the render target from the frame buffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - ID3D11ShaderResourceView *source = sourceRenderTarget->getShaderResourceView(); - if (!source) - { - ERR("Failed to retrieve the render target view from the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - TextureStorage11_Cube *storage11 = TextureStorage11_Cube::makeTextureStorage11_Cube(storage->getStorageInstance()); - if (!storage11) - { - ERR("Failed to retrieve the texture storage from the destination."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RenderTarget11 *destRenderTarget = RenderTarget11::makeRenderTarget11(storage11->getRenderTarget(target, level)); - if (!destRenderTarget) - { - ERR("Failed to retrieve the render target from the destination storage."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - ID3D11RenderTargetView *dest = destRenderTarget->getRenderTargetView(); - if (!dest) - { - ERR("Failed to retrieve the render target view from the destination render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - gl::Rectangle destRect; - destRect.x = xoffset; - destRect.y = yoffset; - destRect.width = sourceRect.width; - destRect.height = sourceRect.height; - - bool ret = copyTexture(source, sourceRect, sourceRenderTarget->getWidth(), sourceRenderTarget->getHeight(), - dest, destRect, destRenderTarget->getWidth(), destRenderTarget->getHeight(), destFormat); - - return ret; -} - -bool Renderer11::copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight, - ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat) -{ - HRESULT result; - - if (!mCopyResourcesInitialized) - { - ASSERT(!mCopyVB && !mCopySampler && !mCopyIL && !mCopyVS && !mCopyRGBAPS && !mCopyRGBPS && !mCopyLumPS && !mCopyLumAlphaPS); - - D3D11_BUFFER_DESC vbDesc; - vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; - vbDesc.Usage = D3D11_USAGE_DYNAMIC; - vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - vbDesc.MiscFlags = 0; - vbDesc.StructureByteStride = 0; - - result = mDevice->CreateBuffer(&vbDesc, NULL, &mCopyVB); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyVB, "Renderer11 copy texture vertex buffer"); - - D3D11_SAMPLER_DESC samplerDesc; - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.MipLODBias = 0.0f; - samplerDesc.MaxAnisotropy = 0; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; - samplerDesc.BorderColor[0] = 0.0f; - samplerDesc.BorderColor[1] = 0.0f; - samplerDesc.BorderColor[2] = 0.0f; - samplerDesc.BorderColor[3] = 0.0f; - samplerDesc.MinLOD = 0.0f; - samplerDesc.MaxLOD = mDevice->GetFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 ? 0.0f : FLT_MAX; - - result = mDevice->CreateSamplerState(&samplerDesc, &mCopySampler); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopySampler, "Renderer11 copy sampler"); - - D3D11_INPUT_ELEMENT_DESC quadLayout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - - result = mDevice->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mCopyIL); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyIL, "Renderer11 copy texture input layout"); - - result = mDevice->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mCopyVS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyVS, "Renderer11 copy texture vertex shader"); - - result = mDevice->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mCopyRGBAPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyRGBAPS, "Renderer11 copy texture RGBA pixel shader"); - - result = mDevice->CreatePixelShader(g_PS_PassthroughRGB, sizeof(g_PS_PassthroughRGB), NULL, &mCopyRGBPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyRGBPS, "Renderer11 copy texture RGB pixel shader"); - - result = mDevice->CreatePixelShader(g_PS_PassthroughLum, sizeof(g_PS_PassthroughLum), NULL, &mCopyLumPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyLumPS, "Renderer11 copy texture luminance pixel shader"); - - result = mDevice->CreatePixelShader(g_PS_PassthroughLumAlpha, sizeof(g_PS_PassthroughLumAlpha), NULL, &mCopyLumAlphaPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mCopyLumAlphaPS, "Renderer11 copy texture luminance alpha pixel shader"); - - mCopyResourcesInitialized = true; - } - - // Verify the source and destination area sizes - if (sourceArea.x < 0 || sourceArea.x + sourceArea.width > static_cast(sourceWidth) || - sourceArea.y < 0 || sourceArea.y + sourceArea.height > static_cast(sourceHeight) || - destArea.x < 0 || destArea.x + destArea.width > static_cast(destWidth) || - destArea.y < 0 || destArea.y + destArea.height > static_cast(destHeight)) - { - return gl::error(GL_INVALID_VALUE, false); - } - - // Set vertices - D3D11_MAPPED_SUBRESOURCE mappedResource; - result = mDeviceContext->Map(mCopyVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Failed to map vertex buffer for texture copy, HRESULT: 0x%X.", result); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - d3d11::PositionTexCoordVertex *vertices = static_cast(mappedResource.pData); - - // Create a quad in homogeneous coordinates - float x1 = (destArea.x / float(destWidth)) * 2.0f - 1.0f; - float y1 = ((destHeight - destArea.y - destArea.height) / float(destHeight)) * 2.0f - 1.0f; - float x2 = ((destArea.x + destArea.width) / float(destWidth)) * 2.0f - 1.0f; - float y2 = ((destHeight - destArea.y) / float(destHeight)) * 2.0f - 1.0f; - - float u1 = sourceArea.x / float(sourceWidth); - float v1 = sourceArea.y / float(sourceHeight); - float u2 = (sourceArea.x + sourceArea.width) / float(sourceWidth); - float v2 = (sourceArea.y + sourceArea.height) / float(sourceHeight); - - d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v2); - d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v1); - d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v2); - d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v1); - - mDeviceContext->Unmap(mCopyVB, 0); - - static UINT stride = sizeof(d3d11::PositionTexCoordVertex); - static UINT startIdx = 0; - mDeviceContext->IASetVertexBuffers(0, 1, &mCopyVB, &stride, &startIdx); - - // Apply state - mDeviceContext->OMSetBlendState(NULL, NULL, 0xFFFFFFF); - mDeviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); - mDeviceContext->RSSetState(NULL); - - // Apply shaders - mDeviceContext->IASetInputLayout(mCopyIL); - mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - mDeviceContext->VSSetShader(mCopyVS, NULL, 0); - - ID3D11PixelShader *ps = NULL; - switch(destFormat) - { - case GL_RGBA: ps = mCopyRGBAPS; break; - case GL_RGB: ps = mCopyRGBPS; break; - case GL_ALPHA: ps = mCopyRGBAPS; break; - case GL_BGRA_EXT: ps = mCopyRGBAPS; break; - case GL_LUMINANCE: ps = mCopyLumPS; break; - case GL_LUMINANCE_ALPHA: ps = mCopyLumAlphaPS; break; - default: UNREACHABLE(); ps = NULL; break; - } - - mDeviceContext->PSSetShader(ps, NULL, 0); - mDeviceContext->GSSetShader(NULL, NULL, 0); - - // Unset the currently bound shader resource to avoid conflicts - static ID3D11ShaderResourceView *const nullSRV = NULL; - mDeviceContext->PSSetShaderResources(0, 1, &nullSRV); - - // Apply render target - setOneTimeRenderTarget(dest); - - // Set the viewport - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = destWidth; - viewport.Height = destHeight; - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - mDeviceContext->RSSetViewports(1, &viewport); - - // Apply textures - mDeviceContext->PSSetShaderResources(0, 1, &source); - mDeviceContext->PSSetSamplers(0, 1, &mCopySampler); - - // Draw the quad - mDeviceContext->Draw(4, 0); - - // Unbind textures and render targets and vertex buffer - mDeviceContext->PSSetShaderResources(0, 1, &nullSRV); - - unapplyRenderTargets(); - - UINT zero = 0; - ID3D11Buffer *const nullBuffer = NULL; - mDeviceContext->IASetVertexBuffers(0, 1, &nullBuffer, &zero, &zero); - - markAllStateDirty(); - - return true; -} - -void Renderer11::unapplyRenderTargets() -{ - setOneTimeRenderTarget(NULL); -} - -void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView) -{ - ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL}; - - rtvArray[0] = renderTargetView; - - mDeviceContext->OMSetRenderTargets(getMaxRenderTargets(), rtvArray, NULL); - - // Do not preserve the serial for this one-time-use render target - for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++) - { - mAppliedRenderTargetSerials[rtIndex] = 0; - } -} - -RenderTarget *Renderer11::createRenderTarget(SwapChain *swapChain, bool depth) -{ - SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); - RenderTarget11 *renderTarget = NULL; - - if (depth) - { - // Note: depth stencil may be NULL for 0 sized surfaces - renderTarget = new RenderTarget11(this, swapChain11->getDepthStencil(), - swapChain11->getDepthStencilTexture(), NULL, - swapChain11->getWidth(), swapChain11->getHeight()); - } - else - { - // Note: render target may be NULL for 0 sized surfaces - renderTarget = new RenderTarget11(this, swapChain11->getRenderTarget(), - swapChain11->getOffscreenTexture(), - swapChain11->getRenderTargetShaderResource(), - swapChain11->getWidth(), swapChain11->getHeight()); - } - return renderTarget; -} - -RenderTarget *Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) -{ - RenderTarget11 *renderTarget = new RenderTarget11(this, width, height, format, samples, depth); - return renderTarget; -} - -ShaderExecutable *Renderer11::loadExecutable(const void *function, size_t length, rx::ShaderType type) -{ - ShaderExecutable11 *executable = NULL; - - switch (type) - { - case rx::SHADER_VERTEX: - { - ID3D11VertexShader *vshader = NULL; - HRESULT result = mDevice->CreateVertexShader(function, length, NULL, &vshader); - ASSERT(SUCCEEDED(result)); - - if (vshader) - { - executable = new ShaderExecutable11(function, length, vshader); - } - } - break; - case rx::SHADER_PIXEL: - { - ID3D11PixelShader *pshader = NULL; - HRESULT result = mDevice->CreatePixelShader(function, length, NULL, &pshader); - ASSERT(SUCCEEDED(result)); - - if (pshader) - { - executable = new ShaderExecutable11(function, length, pshader); - } - } - break; - case rx::SHADER_GEOMETRY: - { - ID3D11GeometryShader *gshader = NULL; - HRESULT result = mDevice->CreateGeometryShader(function, length, NULL, &gshader); - ASSERT(SUCCEEDED(result)); - - if (gshader) - { - executable = new ShaderExecutable11(function, length, gshader); - } - } - break; - default: - UNREACHABLE(); - break; - } - - return executable; -} - -ShaderExecutable *Renderer11::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) -{ - std::string profile; - - switch (type) - { - case rx::SHADER_VERTEX: - profile = "vs_4_0"; - break; - case rx::SHADER_PIXEL: - profile = "ps_4_0"; - break; - case rx::SHADER_GEOMETRY: - profile = "gs_4_0"; - break; - default: - UNREACHABLE(); - return NULL; - } - - if (mFeatureLevel == D3D_FEATURE_LEVEL_9_3) - profile += "_level_9_3"; - else if (mFeatureLevel == D3D_FEATURE_LEVEL_9_2 || mFeatureLevel == D3D_FEATURE_LEVEL_9_1) - profile += "_level_9_1"; - - ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile.c_str(), D3DCOMPILE_OPTIMIZATION_LEVEL0, false); - if (!binary) - return NULL; - - ShaderExecutable *executable = loadExecutable((DWORD *)binary->GetBufferPointer(), binary->GetBufferSize(), type); - binary->Release(); - - return executable; -} - -VertexBuffer *Renderer11::createVertexBuffer() -{ - return new VertexBuffer11(this); -} - -IndexBuffer *Renderer11::createIndexBuffer() -{ - return new IndexBuffer11(this); -} - -BufferStorage *Renderer11::createBufferStorage() -{ - return new BufferStorage11(this); -} - -QueryImpl *Renderer11::createQuery(GLenum type) -{ - return new Query11(this, type); -} - -FenceImpl *Renderer11::createFence() -{ - return new Fence11(this); -} - -bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource) -{ - ASSERT(colorbuffer != NULL); - - RenderTarget11 *renderTarget = RenderTarget11::makeRenderTarget11(colorbuffer->getRenderTarget()); - if (renderTarget) - { - *subresourceIndex = renderTarget->getSubresourceIndex(); - - ID3D11RenderTargetView *colorBufferRTV = renderTarget->getRenderTargetView(); - if (colorBufferRTV) - { - ID3D11Resource *textureResource = NULL; - colorBufferRTV->GetResource(&textureResource); - - if (textureResource) - { - HRESULT result = textureResource->QueryInterface(IID_ID3D11Texture2D, (void**)resource); - textureResource->Release(); - - if (SUCCEEDED(result)) - { - return true; - } - else - { - ERR("Failed to extract the ID3D11Texture2D from the render target resource, " - "HRESULT: 0x%X.", result); - } - } - } - } - - return false; -} - -bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - bool blitRenderTarget, bool blitDepthStencil) -{ - if (blitRenderTarget) - { - gl::Renderbuffer *readBuffer = readTarget->getReadColorbuffer(); - - if (!readBuffer) - { - ERR("Failed to retrieve the read buffer from the read framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RenderTarget *readRenderTarget = readBuffer->getRenderTarget(); - - for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) - { - if (drawTarget->isEnabledColorAttachment(colorAttachment)) - { - gl::Renderbuffer *drawBuffer = drawTarget->getColorbuffer(colorAttachment); - - if (!drawBuffer) - { - ERR("Failed to retrieve the draw buffer from the draw framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget(); - - if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, false)) - { - return false; - } - } - } - } - - if (blitDepthStencil) - { - gl::Renderbuffer *readBuffer = readTarget->getDepthOrStencilbuffer(); - gl::Renderbuffer *drawBuffer = drawTarget->getDepthOrStencilbuffer(); - - if (!readBuffer) - { - ERR("Failed to retrieve the read depth-stencil buffer from the read framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - if (!drawBuffer) - { - ERR("Failed to retrieve the draw depth-stencil buffer from the draw framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RenderTarget *readRenderTarget = readBuffer->getDepthStencil(); - RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil(); - - if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, true)) - { - return false; - } - } - - return true; -} - -void Renderer11::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) -{ - ID3D11Texture2D *colorBufferTexture = NULL; - unsigned int subresourceIndex = 0; - - gl::Renderbuffer *colorbuffer = framebuffer->getReadColorbuffer(); - - if (colorbuffer && getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture)) - { - gl::Rectangle area; - area.x = x; - area.y = y; - area.width = width; - area.height = height; - - readTextureData(colorBufferTexture, subresourceIndex, area, colorbuffer->getActualFormat(), format, type, outputPitch, - packReverseRowOrder, packAlignment, pixels); - - colorBufferTexture->Release(); - colorBufferTexture = NULL; - } -} - -Image *Renderer11::createImage() -{ - return new Image11(); -} - -void Renderer11::generateMipmap(Image *dest, Image *src) -{ - Image11 *dest11 = Image11::makeImage11(dest); - Image11 *src11 = Image11::makeImage11(src); - Image11::generateMipmap(dest11, src11); -} - -TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain) -{ - SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain); - return new TextureStorage11_2D(this, swapChain11); -} - -TextureStorage *Renderer11::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) -{ - return new TextureStorage11_2D(this, levels, internalformat, usage, forceRenderable, width, height); -} - -TextureStorage *Renderer11::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) -{ - return new TextureStorage11_Cube(this, levels, internalformat, usage, forceRenderable, size); -} - -static inline unsigned int getFastPixelCopySize(DXGI_FORMAT sourceFormat, GLenum sourceGLFormat, GLenum destFormat, GLenum destType) -{ - if (sourceFormat == DXGI_FORMAT_A8_UNORM && - destFormat == GL_ALPHA && - destType == GL_UNSIGNED_BYTE) - { - return 1; - } - else if (sourceFormat == DXGI_FORMAT_R8G8B8A8_UNORM && - sourceGLFormat == GL_RGBA8_OES && - destFormat == GL_RGBA && - destType == GL_UNSIGNED_BYTE) - { - return 4; - } - else if (sourceFormat == DXGI_FORMAT_B8G8R8A8_UNORM && - destFormat == GL_BGRA_EXT && - destType == GL_UNSIGNED_BYTE) - { - return 4; - } - else if (sourceFormat == DXGI_FORMAT_R16G16B16A16_FLOAT && - sourceGLFormat == GL_RGBA16F_EXT && - destFormat == GL_RGBA && - destType == GL_HALF_FLOAT_OES) - { - return 8; - } - else if (sourceFormat == DXGI_FORMAT_R32G32B32_FLOAT && - destFormat == GL_RGB && - destType == GL_FLOAT) - { - return 12; - } - else if (sourceFormat == DXGI_FORMAT_R32G32B32A32_FLOAT && - sourceGLFormat == GL_RGBA32F_EXT && - destFormat == GL_RGBA && - destType == GL_FLOAT) - { - return 16; - } - else - { - return 0; - } -} - -static inline void readPixelColor(const unsigned char *data, DXGI_FORMAT format, GLenum glFormat, unsigned int x, - unsigned int y, int inputPitch, gl::Color *outColor) -{ - switch (format) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - { - unsigned int rgba = *reinterpret_cast(data + 4 * x + y * inputPitch); - outColor->red = (rgba & 0x000000FF) * (1.0f / 0x000000FF); - outColor->green = (rgba & 0x0000FF00) * (1.0f / 0x0000FF00); - outColor->blue = (rgba & 0x00FF0000) * (1.0f / 0x00FF0000); - - if (gl::GetAlphaSize(glFormat) > 0) - { - outColor->alpha = (rgba & 0xFF000000) * (1.0f / 0xFF000000); - } - else - { - outColor->alpha = 1.0f; - } - } - break; - - case DXGI_FORMAT_A8_UNORM: - { - outColor->red = 0.0f; - outColor->green = 0.0f; - outColor->blue = 0.0f; - outColor->alpha = *(data + x + y * inputPitch) / 255.0f; - } - break; - - case DXGI_FORMAT_R32G32B32A32_FLOAT: - { - outColor->red = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 0); - outColor->green = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 1); - outColor->blue = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 2); - - if (gl::GetAlphaSize(glFormat) > 0) - { - outColor->alpha = *(reinterpret_cast(data + 16 * x + y * inputPitch) + 3); - } - else - { - outColor->alpha = 1.0f; - } - } - break; - - case DXGI_FORMAT_R32G32B32_FLOAT: - { - outColor->red = *(reinterpret_cast(data + 12 * x + y * inputPitch) + 0); - outColor->green = *(reinterpret_cast(data + 12 * x + y * inputPitch) + 1); - outColor->blue = *(reinterpret_cast(data + 12 * x + y * inputPitch) + 2); - outColor->alpha = 1.0f; - } - break; - - case DXGI_FORMAT_R16G16B16A16_FLOAT: - { - outColor->red = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 0)); - outColor->green = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 1)); - outColor->blue = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 2)); - - if (gl::GetAlphaSize(glFormat) > 0) - { - outColor->alpha = gl::float16ToFloat32(*(reinterpret_cast(data + 8 * x + y * inputPitch) + 3)); - } - else - { - outColor->alpha = 1.0f; - } - } - break; - - case DXGI_FORMAT_B8G8R8A8_UNORM: - { - unsigned int bgra = *reinterpret_cast(data + 4 * x + y * inputPitch); - outColor->red = (bgra & 0x00FF0000) * (1.0f / 0x00FF0000); - outColor->blue = (bgra & 0x000000FF) * (1.0f / 0x000000FF); - outColor->green = (bgra & 0x0000FF00) * (1.0f / 0x0000FF00); - outColor->alpha = (bgra & 0xFF000000) * (1.0f / 0xFF000000); - } - break; - - case DXGI_FORMAT_R8_UNORM: - { - outColor->red = *(data + x + y * inputPitch) / 255.0f; - outColor->green = 0.0f; - outColor->blue = 0.0f; - outColor->alpha = 1.0f; - } - break; - - case DXGI_FORMAT_R8G8_UNORM: - { - unsigned short rg = *reinterpret_cast(data + 2 * x + y * inputPitch); - - outColor->red = (rg & 0xFF00) * (1.0f / 0xFF00); - outColor->green = (rg & 0x00FF) * (1.0f / 0x00FF); - outColor->blue = 0.0f; - outColor->alpha = 1.0f; - } - break; - - case DXGI_FORMAT_R16_FLOAT: - { - outColor->red = gl::float16ToFloat32(*reinterpret_cast(data + 2 * x + y * inputPitch)); - outColor->green = 0.0f; - outColor->blue = 0.0f; - outColor->alpha = 1.0f; - } - break; - - case DXGI_FORMAT_R16G16_FLOAT: - { - outColor->red = gl::float16ToFloat32(*(reinterpret_cast(data + 4 * x + y * inputPitch) + 0)); - outColor->green = gl::float16ToFloat32(*(reinterpret_cast(data + 4 * x + y * inputPitch) + 1)); - outColor->blue = 0.0f; - outColor->alpha = 1.0f; - } - break; - - default: - ERR("ReadPixelColor not implemented for DXGI format %u.", format); - UNIMPLEMENTED(); - break; - } -} - -static inline void writePixelColor(const gl::Color &color, GLenum format, GLenum type, unsigned int x, - unsigned int y, int outputPitch, void *outData) -{ - unsigned char* byteData = reinterpret_cast(outData); - unsigned short* shortData = reinterpret_cast(outData); - - switch (format) - { - case GL_RGBA: - switch (type) - { - case GL_UNSIGNED_BYTE: - byteData[4 * x + y * outputPitch + 0] = static_cast(255 * color.red + 0.5f); - byteData[4 * x + y * outputPitch + 1] = static_cast(255 * color.green + 0.5f); - byteData[4 * x + y * outputPitch + 2] = static_cast(255 * color.blue + 0.5f); - byteData[4 * x + y * outputPitch + 3] = static_cast(255 * color.alpha + 0.5f); - break; - - default: - ERR("WritePixelColor not implemented for format GL_RGBA and type 0x%X.", type); - UNIMPLEMENTED(); - break; - } - break; - - case GL_BGRA_EXT: - switch (type) - { - case GL_UNSIGNED_BYTE: - byteData[4 * x + y * outputPitch + 0] = static_cast(255 * color.blue + 0.5f); - byteData[4 * x + y * outputPitch + 1] = static_cast(255 * color.green + 0.5f); - byteData[4 * x + y * outputPitch + 2] = static_cast(255 * color.red + 0.5f); - byteData[4 * x + y * outputPitch + 3] = static_cast(255 * color.alpha + 0.5f); - break; - - case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - shortData[x + y * outputPitch / sizeof(unsigned short)] = - (static_cast(15 * color.alpha + 0.5f) << 12) | - (static_cast(15 * color.red + 0.5f) << 8) | - (static_cast(15 * color.green + 0.5f) << 4) | - (static_cast(15 * color.blue + 0.5f) << 0); - break; - - case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - shortData[x + y * outputPitch / sizeof(unsigned short)] = - (static_cast( color.alpha + 0.5f) << 15) | - (static_cast(31 * color.red + 0.5f) << 10) | - (static_cast(31 * color.green + 0.5f) << 5) | - (static_cast(31 * color.blue + 0.5f) << 0); - break; - - default: - ERR("WritePixelColor not implemented for format GL_BGRA_EXT and type 0x%X.", type); - UNIMPLEMENTED(); - break; - } - break; - - case GL_RGB: - switch (type) - { - case GL_UNSIGNED_SHORT_5_6_5: - shortData[x + y * outputPitch / sizeof(unsigned short)] = - (static_cast(31 * color.blue + 0.5f) << 0) | - (static_cast(63 * color.green + 0.5f) << 5) | - (static_cast(31 * color.red + 0.5f) << 11); - break; - - case GL_UNSIGNED_BYTE: - byteData[3 * x + y * outputPitch + 0] = static_cast(255 * color.red + 0.5f); - byteData[3 * x + y * outputPitch + 1] = static_cast(255 * color.green + 0.5f); - byteData[3 * x + y * outputPitch + 2] = static_cast(255 * color.blue + 0.5f); - break; - - default: - ERR("WritePixelColor not implemented for format GL_RGB and type 0x%X.", type); - UNIMPLEMENTED(); - break; - } - break; - - default: - ERR("WritePixelColor not implemented for format 0x%X.", format); - UNIMPLEMENTED(); - break; - } -} - -void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, - GLenum sourceFormat, GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder, - GLint packAlignment, void *pixels) -{ - D3D11_TEXTURE2D_DESC textureDesc; - texture->GetDesc(&textureDesc); - - D3D11_TEXTURE2D_DESC stagingDesc; - stagingDesc.Width = area.width; - stagingDesc.Height = area.height; - stagingDesc.MipLevels = 1; - stagingDesc.ArraySize = 1; - stagingDesc.Format = textureDesc.Format; - stagingDesc.SampleDesc.Count = 1; - stagingDesc.SampleDesc.Quality = 0; - stagingDesc.Usage = D3D11_USAGE_STAGING; - stagingDesc.BindFlags = 0; - stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; - stagingDesc.MiscFlags = 0; - - ID3D11Texture2D* stagingTex = NULL; - HRESULT result = mDevice->CreateTexture2D(&stagingDesc, NULL, &stagingTex); - if (FAILED(result)) - { - ERR("Failed to create staging texture for readPixels, HRESULT: 0x%X.", result); - return; - } - - ID3D11Texture2D* srcTex = NULL; - if (textureDesc.SampleDesc.Count > 1) - { - D3D11_TEXTURE2D_DESC resolveDesc; - resolveDesc.Width = textureDesc.Width; - resolveDesc.Height = textureDesc.Height; - resolveDesc.MipLevels = 1; - resolveDesc.ArraySize = 1; - resolveDesc.Format = textureDesc.Format; - resolveDesc.SampleDesc.Count = 1; - resolveDesc.SampleDesc.Quality = 0; - resolveDesc.Usage = D3D11_USAGE_DEFAULT; - resolveDesc.BindFlags = 0; - resolveDesc.CPUAccessFlags = 0; - resolveDesc.MiscFlags = 0; - - result = mDevice->CreateTexture2D(&resolveDesc, NULL, &srcTex); - if (FAILED(result)) - { - ERR("Failed to create resolve texture for readPixels, HRESULT: 0x%X.", result); - stagingTex->Release(); - return; - } - - mDeviceContext->ResolveSubresource(srcTex, 0, texture, subResource, textureDesc.Format); - subResource = 0; - } - else - { - srcTex = texture; - srcTex->AddRef(); - } - - D3D11_BOX srcBox; - srcBox.left = area.x; - srcBox.right = area.x + area.width; - srcBox.top = area.y; - srcBox.bottom = area.y + area.height; - srcBox.front = 0; - srcBox.back = 1; - - mDeviceContext->CopySubresourceRegion(stagingTex, 0, 0, 0, 0, srcTex, subResource, &srcBox); - - srcTex->Release(); - srcTex = NULL; - - D3D11_MAPPED_SUBRESOURCE mapping; - mDeviceContext->Map(stagingTex, 0, D3D11_MAP_READ, 0, &mapping); - - unsigned char *source; - int inputPitch; - if (packReverseRowOrder) - { - source = static_cast(mapping.pData) + mapping.RowPitch * (area.height - 1); - inputPitch = -static_cast(mapping.RowPitch); - } - else - { - source = static_cast(mapping.pData); - inputPitch = static_cast(mapping.RowPitch); - } - - unsigned int fastPixelSize = getFastPixelCopySize(textureDesc.Format, sourceFormat, format, type); - if (fastPixelSize != 0) - { - unsigned char *dest = static_cast(pixels); - for (int j = 0; j < area.height; j++) - { - memcpy(dest + j * outputPitch, source + j * inputPitch, area.width * fastPixelSize); - } - } - else if (textureDesc.Format == DXGI_FORMAT_B8G8R8A8_UNORM && - format == GL_RGBA && - type == GL_UNSIGNED_BYTE) - { - // Fast path for swapping red with blue - unsigned char *dest = static_cast(pixels); - - for (int j = 0; j < area.height; j++) - { - for (int i = 0; i < area.width; i++) - { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); - *(unsigned int*)(dest + 4 * i + j * outputPitch) = - (argb & 0xFF00FF00) | // Keep alpha and green - (argb & 0x00FF0000) >> 16 | // Move red to blue - (argb & 0x000000FF) << 16; // Move blue to red - } - } - } - else - { - gl::Color pixelColor; - for (int j = 0; j < area.height; j++) - { - for (int i = 0; i < area.width; i++) - { - readPixelColor(source, textureDesc.Format, sourceFormat, i, j, inputPitch, &pixelColor); - writePixelColor(pixelColor, format, type, i, j, outputPitch, pixels); - } - } - } - - mDeviceContext->Unmap(stagingTex, 0); - - stagingTex->Release(); - stagingTex = NULL; -} - -bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, - RenderTarget *drawRenderTarget, bool wholeBufferCopy) -{ - ASSERT(readRect.width == drawRect.width && readRect.height == drawRect.height); - - RenderTarget11 *drawRenderTarget11 = RenderTarget11::makeRenderTarget11(drawRenderTarget); - if (!drawRenderTarget) - { - ERR("Failed to retrieve the draw render target from the draw framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - ID3D11Texture2D *drawTexture = drawRenderTarget11->getTexture(); - unsigned int drawSubresource = drawRenderTarget11->getSubresourceIndex(); - - RenderTarget11 *readRenderTarget11 = RenderTarget11::makeRenderTarget11(readRenderTarget); - if (!readRenderTarget) - { - ERR("Failed to retrieve the read render target from the read framebuffer."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - ID3D11Texture2D *readTexture = NULL; - unsigned int readSubresource = 0; - if (readRenderTarget->getSamples() > 0) - { - readTexture = resolveMultisampledTexture(readRenderTarget11->getTexture(), readRenderTarget11->getSubresourceIndex()); - readSubresource = 0; - } - else - { - readTexture = readRenderTarget11->getTexture(); - readTexture->AddRef(); - readSubresource = readRenderTarget11->getSubresourceIndex(); - } - - if (!readTexture) - { - ERR("Failed to retrieve the read render target view from the read render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - D3D11_BOX readBox; - readBox.left = readRect.x; - readBox.right = readRect.x + readRect.width; - readBox.top = readRect.y; - readBox.bottom = readRect.y + readRect.height; - readBox.front = 0; - readBox.back = 1; - - // D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox - // We also require complete framebuffer copies for depth-stencil blit. - D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox; - - mDeviceContext->CopySubresourceRegion(drawTexture, drawSubresource, drawRect.x, drawRect.y, 0, - readTexture, readSubresource, pSrcBox); - - SafeRelease(readTexture); - - return true; -} - -ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource) -{ - D3D11_TEXTURE2D_DESC textureDesc; - source->GetDesc(&textureDesc); - - if (textureDesc.SampleDesc.Count > 1) - { - D3D11_TEXTURE2D_DESC resolveDesc; - resolveDesc.Width = textureDesc.Width; - resolveDesc.Height = textureDesc.Height; - resolveDesc.MipLevels = 1; - resolveDesc.ArraySize = 1; - resolveDesc.Format = textureDesc.Format; - resolveDesc.SampleDesc.Count = 1; - resolveDesc.SampleDesc.Quality = 0; - resolveDesc.Usage = textureDesc.Usage; - resolveDesc.BindFlags = textureDesc.BindFlags; - resolveDesc.CPUAccessFlags = 0; - resolveDesc.MiscFlags = 0; - - ID3D11Texture2D *resolveTexture = NULL; - HRESULT result = mDevice->CreateTexture2D(&resolveDesc, NULL, &resolveTexture); - if (FAILED(result)) - { - ERR("Failed to create a multisample resolve texture, HRESULT: 0x%X.", result); - return NULL; - } - - mDeviceContext->ResolveSubresource(resolveTexture, 0, source, subresource, textureDesc.Format); - return resolveTexture; - } - else - { - source->AddRef(); - return source; - } -} - -bool Renderer11::getLUID(LUID *adapterLuid) const -{ - adapterLuid->HighPart = 0; - adapterLuid->LowPart = 0; - - if (!mDxgiAdapter) - { - return false; - } - - DXGI_ADAPTER_DESC adapterDesc; - if (FAILED(mDxgiAdapter->GetDesc(&adapterDesc))) - { - return false; - } - - *adapterLuid = adapterDesc.AdapterLuid; - return true; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h deleted file mode 100644 index 773fc26db1..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h +++ /dev/null @@ -1,373 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Renderer11.h: Defines a back-end specific class for the D3D11 renderer. - -#ifndef LIBGLESV2_RENDERER_RENDERER11_H_ -#define LIBGLESV2_RENDERER_RENDERER11_H_ - -#include "common/angleutils.h" -#include "libGLESv2/angletypes.h" -#include "libGLESv2/mathutil.h" - -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/d3d11/RenderStateCache.h" -#include "libGLESv2/renderer/d3d11/InputLayoutCache.h" -#include "libGLESv2/renderer/RenderTarget.h" - -#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) -struct IInspectable; -namespace ABI { - namespace Windows { - namespace ApplicationModel { - struct ISuspendingEventArgs; - } - } -} -#endif - -namespace gl -{ -class Renderbuffer; -} - -namespace rx -{ - -class VertexDataManager; -class IndexDataManager; -class StreamingIndexBufferInterface; - -enum -{ - MAX_VERTEX_UNIFORM_VECTORS_D3D11 = 1024, - MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024 -}; - -class Renderer11 : public Renderer -{ - public: - Renderer11(egl::Display *display); - virtual ~Renderer11(); - - static Renderer11 *makeRenderer11(Renderer *renderer); - - virtual EGLint initialize(); - virtual bool resetDevice(); - - virtual int generateConfigs(ConfigDesc **configDescList); - virtual void deleteConfigs(ConfigDesc *configDescList); - - virtual void sync(bool block); - - virtual SwapChain *createSwapChain(EGLNativeWindowType window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); - - virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); - virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); - - virtual void setRasterizerState(const gl::RasterizerState &rasterState); - virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, - unsigned int sampleMask); - virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW); - - virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); - virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport); - - virtual bool applyPrimitiveType(GLenum mode, GLsizei count); - virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); - virtual void applyShaders(gl::ProgramBinary *programBinary); - virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray); - virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances); - virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); - - virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances); - virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); - - virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); - - virtual void markAllStateDirty(); - - // lost device - void notifyDeviceLost(); - virtual bool isDeviceLost(); - virtual bool testDeviceLost(bool notify); - virtual bool testDeviceResettable(); - - // Renderer capabilities - virtual DWORD getAdapterVendor() const; - virtual std::string getRendererDescription() const; - virtual GUID getAdapterIdentifier() const; - - virtual bool getBGRATextureSupport() const; - virtual bool getDXT1TextureSupport(); - virtual bool getDXT3TextureSupport(); - virtual bool getDXT5TextureSupport(); - virtual bool getEventQuerySupport(); - virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable); - virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable); - virtual bool getLuminanceTextureSupport(); - virtual bool getLuminanceAlphaTextureSupport(); - virtual unsigned int getMaxVertexTextureImageUnits() const; - virtual unsigned int getMaxCombinedTextureImageUnits() const; - virtual unsigned int getReservedVertexUniformVectors() const; - virtual unsigned int getReservedFragmentUniformVectors() const; - virtual unsigned int getMaxVertexUniformVectors() const; - virtual unsigned int getMaxFragmentUniformVectors() const; - virtual unsigned int getMaxVaryingVectors() const; - virtual bool getNonPower2TextureSupport() const; - virtual bool getDepthTextureSupport() const; - virtual bool getOcclusionQuerySupport() const; - virtual bool getInstancingSupport() const; - virtual bool getTextureFilterAnisotropySupport() const; - virtual float getTextureMaxAnisotropy() const; - virtual bool getShareHandleSupport() const; - virtual bool getDerivativeInstructionSupport() const; - virtual bool getPostSubBufferSupport() const; - - virtual int getMajorShaderModel() const; - virtual float getMaxPointSize() const; - virtual int getMaxViewportDimension() const; - virtual int getMaxTextureWidth() const; - virtual int getMaxTextureHeight() const; - virtual bool get32BitIndexSupport() const; - virtual int getMinSwapInterval() const; - virtual int getMaxSwapInterval() const; - - virtual GLsizei getMaxSupportedSamples() const; - int getNearestSupportedSamples(DXGI_FORMAT format, unsigned int requested) const; - - virtual unsigned int getMaxRenderTargets() const; - - // Pixel operations - virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source); - virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source); - - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); - - bool copyTexture(ID3D11ShaderResourceView *source, const gl::Rectangle &sourceArea, unsigned int sourceWidth, unsigned int sourceHeight, - ID3D11RenderTargetView *dest, const gl::Rectangle &destArea, unsigned int destWidth, unsigned int destHeight, GLenum destFormat); - - virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - bool blitRenderTarget, bool blitDepthStencil); - virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels); - - // RenderTarget creation - virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); - virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth); - - // Shader operations - virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type); - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround); - - // Image operations - virtual Image *createImage(); - virtual void generateMipmap(Image *dest, Image *source); - virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); - virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); - virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); - - // Buffer creation - virtual VertexBuffer *createVertexBuffer(); - virtual IndexBuffer *createIndexBuffer(); - virtual BufferStorage *createBufferStorage(); - - // Query and Fence creation - virtual QueryImpl *createQuery(GLenum type); - virtual FenceImpl *createFence(); - - // D3D11-renderer specific methods - ID3D11Device *getDevice() { return mDevice; } - ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; }; - IDXGIFactory *getDxgiFactory() { return mDxgiFactory; }; - D3D_FEATURE_LEVEL getFeatureLevel() { return mFeatureLevel; } - - bool getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned int *subresourceIndex, ID3D11Texture2D **resource); - void unapplyRenderTargets(); - void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView); - - virtual bool getLUID(LUID *adapterLuid) const; - - private: - DISALLOW_COPY_AND_ASSIGN(Renderer11); - - void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); - void drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances); - - void readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, - GLenum sourceFormat, GLenum format, GLenum type, GLsizei outputPitch, bool packReverseRowOrder, - GLint packAlignment, void *pixels); - - void maskedClear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); - rx::Range getViewportBounds() const; - - bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget, - RenderTarget *drawRenderTarget, bool wholeBufferCopy); - ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource); - -#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE) - HRESULT onSuspend(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *); -#endif - - HMODULE mD3d11Module; - HMODULE mDxgiModule; - - bool mDeviceLost; - - void initializeDevice(); - void releaseDeviceResources(); - int getMinorShaderModel() const; - void release(); - - RenderStateCache mStateCache; - - // Support flags - bool mFloat16TextureSupport; - bool mFloat16FilterSupport; - bool mFloat16RenderSupport; - - bool mFloat32TextureSupport; - bool mFloat32FilterSupport; - bool mFloat32RenderSupport; - - bool mDXT1TextureSupport; - bool mDXT3TextureSupport; - bool mDXT5TextureSupport; - - bool mDepthTextureSupport; - - // Multisample format support - struct MultisampleSupportInfo - { - unsigned int qualityLevels[D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT]; - }; - - typedef std::unordered_map > MultisampleSupportMap; - MultisampleSupportMap mMultisampleSupportMap; - - unsigned int mMaxSupportedSamples; - - // current render target states - unsigned int mAppliedRenderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS]; - unsigned int mAppliedDepthbufferSerial; - unsigned int mAppliedStencilbufferSerial; - bool mDepthStencilInitialized; - bool mRenderTargetDescInitialized; - rx::RenderTarget::Desc mRenderTargetDesc; - unsigned int mCurDepthSize; - unsigned int mCurStencilSize; - - // Currently applied sampler states - bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - - bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; - gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; - - // Currently applied textures - unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS]; - - // Currently applied blend state - bool mForceSetBlendState; - gl::BlendState mCurBlendState; - gl::Color mCurBlendColor; - unsigned int mCurSampleMask; - - // Currently applied rasterizer state - bool mForceSetRasterState; - gl::RasterizerState mCurRasterState; - - // Currently applied depth stencil state - bool mForceSetDepthStencilState; - gl::DepthStencilState mCurDepthStencilState; - int mCurStencilRef; - int mCurStencilBackRef; - - // Currently applied scissor rectangle - bool mForceSetScissor; - bool mScissorEnabled; - gl::Rectangle mCurScissor; - - // Currently applied viewport - bool mForceSetViewport; - gl::Rectangle mCurViewport; - float mCurNear; - float mCurFar; - - // Currently applied primitive topology - D3D11_PRIMITIVE_TOPOLOGY mCurrentPrimitiveTopology; - - unsigned int mAppliedIBSerial; - unsigned int mAppliedStorageIBSerial; - unsigned int mAppliedIBOffset; - - unsigned int mAppliedProgramBinarySerial; - bool mIsGeometryShaderActive; - - dx_VertexConstants mVertexConstants; - dx_VertexConstants mAppliedVertexConstants; - ID3D11Buffer *mDriverConstantBufferVS; - ID3D11Buffer *mCurrentVertexConstantBuffer; - - dx_PixelConstants mPixelConstants; - dx_PixelConstants mAppliedPixelConstants; - ID3D11Buffer *mDriverConstantBufferPS; - ID3D11Buffer *mCurrentPixelConstantBuffer; - - ID3D11Buffer *mCurrentGeometryConstantBuffer; - - // Vertex, index and input layouts - VertexDataManager *mVertexDataManager; - IndexDataManager *mIndexDataManager; - InputLayoutCache mInputLayoutCache; - - StreamingIndexBufferInterface *mLineLoopIB; - StreamingIndexBufferInterface *mTriangleFanIB; - - // Texture copy resources - bool mCopyResourcesInitialized; - ID3D11Buffer *mCopyVB; - ID3D11SamplerState *mCopySampler; - ID3D11InputLayout *mCopyIL; - ID3D11VertexShader *mCopyVS; - ID3D11PixelShader *mCopyRGBAPS; - ID3D11PixelShader *mCopyRGBPS; - ID3D11PixelShader *mCopyLumPS; - ID3D11PixelShader *mCopyLumAlphaPS; - - // Masked clear resources - bool mClearResourcesInitialized; - ID3D11Buffer *mClearVB; - ID3D11InputLayout *mClearIL; - ID3D11VertexShader *mClearVS; - ID3D11PixelShader *mClearSinglePS; - ID3D11PixelShader *mClearMultiplePS; - ID3D11RasterizerState *mClearScissorRS; - ID3D11RasterizerState *mClearNoScissorRS; - - // Sync query - ID3D11Query *mSyncQuery; - - ID3D11Device *mDevice; - D3D_FEATURE_LEVEL mFeatureLevel; - ID3D11DeviceContext *mDeviceContext; - IDXGIAdapter *mDxgiAdapter; - DXGI_ADAPTER_DESC mAdapterDescription; - char mDescription[128]; - IDXGIFactory *mDxgiFactory; - - // Cached device caps - bool mBGRATextureSupport; -}; - -} -#endif // LIBGLESV2_RENDERER_RENDERER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp deleted file mode 100644 index 2e455e3af5..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.cpp +++ /dev/null @@ -1,109 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ShaderExecutable11.cpp: Implements a D3D11-specific class to contain shader -// executable implementation details. - -#include "libGLESv2/renderer/d3d11/ShaderExecutable11.h" - -#include "common/debug.h" - -namespace rx -{ - -ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable) - : ShaderExecutable(function, length) -{ - mPixelExecutable = executable; - mVertexExecutable = NULL; - mGeometryExecutable = NULL; - - mConstantBuffer = NULL; -} - -ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable) - : ShaderExecutable(function, length) -{ - mVertexExecutable = executable; - mPixelExecutable = NULL; - mGeometryExecutable = NULL; - - mConstantBuffer = NULL; -} - -ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable) - : ShaderExecutable(function, length) -{ - mGeometryExecutable = executable; - mVertexExecutable = NULL; - mPixelExecutable = NULL; - - mConstantBuffer = NULL; -} - -ShaderExecutable11::~ShaderExecutable11() -{ - if (mVertexExecutable) - { - mVertexExecutable->Release(); - } - if (mPixelExecutable) - { - mPixelExecutable->Release(); - } - if (mGeometryExecutable) - { - mGeometryExecutable->Release(); - } - - if (mConstantBuffer) - { - mConstantBuffer->Release(); - } -} - -ShaderExecutable11 *ShaderExecutable11::makeShaderExecutable11(ShaderExecutable *executable) -{ - ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable11*, executable)); - return static_cast(executable); -} - -ID3D11VertexShader *ShaderExecutable11::getVertexShader() const -{ - return mVertexExecutable; -} - -ID3D11PixelShader *ShaderExecutable11::getPixelShader() const -{ - return mPixelExecutable; -} - -ID3D11GeometryShader *ShaderExecutable11::getGeometryShader() const -{ - return mGeometryExecutable; -} - -ID3D11Buffer *ShaderExecutable11::getConstantBuffer(ID3D11Device *device, unsigned int registerCount) -{ - if (!mConstantBuffer && registerCount > 0) - { - D3D11_BUFFER_DESC constantBufferDescription = {0}; - constantBufferDescription.ByteWidth = registerCount * sizeof(float[4]); - constantBufferDescription.Usage = D3D11_USAGE_DYNAMIC; - constantBufferDescription.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - constantBufferDescription.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - constantBufferDescription.MiscFlags = 0; - constantBufferDescription.StructureByteStride = 0; - - HRESULT result = device->CreateBuffer(&constantBufferDescription, NULL, &mConstantBuffer); - ASSERT(SUCCEEDED(result)); - } - - return mConstantBuffer; -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h deleted file mode 100644 index c6ec1cf7d2..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/ShaderExecutable11.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ShaderExecutable11.h: Defines a D3D11-specific class to contain shader -// executable implementation details. - -#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ -#define LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ - -#include "libGLESv2/renderer/ShaderExecutable.h" - -namespace rx -{ - -class ShaderExecutable11 : public ShaderExecutable -{ - public: - ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable); - ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable); - ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable); - - virtual ~ShaderExecutable11(); - - static ShaderExecutable11 *makeShaderExecutable11(ShaderExecutable *executable); - - ID3D11PixelShader *getPixelShader() const; - ID3D11VertexShader *getVertexShader() const; - ID3D11GeometryShader *getGeometryShader() const; - - ID3D11Buffer *getConstantBuffer(ID3D11Device *device, unsigned int registerCount); - - private: - DISALLOW_COPY_AND_ASSIGN(ShaderExecutable11); - - ID3D11PixelShader *mPixelExecutable; - ID3D11VertexShader *mVertexExecutable; - ID3D11GeometryShader *mGeometryExecutable; - - ID3D11Buffer *mConstantBuffer; -}; - -} - -#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp deleted file mode 100644 index bd97d5cff5..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.cpp +++ /dev/null @@ -1,700 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain. - -#include "libGLESv2/renderer/d3d11/SwapChain11.h" - -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" - -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthrough11vs.h" -#include "libGLESv2/renderer/d3d11/shaders/compiled/passthroughrgba11ps.h" - -namespace rx -{ - -SwapChain11::SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat) - : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) -{ - mSwapChain = NULL; - mBackBufferTexture = NULL; - mBackBufferRTView = NULL; - mOffscreenTexture = NULL; - mOffscreenRTView = NULL; - mOffscreenSRView = NULL; - mDepthStencilTexture = NULL; - mDepthStencilDSView = NULL; - mQuadVB = NULL; - mPassThroughSampler = NULL; - mPassThroughIL = NULL; - mPassThroughVS = NULL; - mPassThroughPS = NULL; - mWidth = -1; - mHeight = -1; - mSwapInterval = 0; - mAppCreatedShareHandle = mShareHandle != NULL; - mPassThroughResourcesInit = false; -} - -SwapChain11::~SwapChain11() -{ - release(); -} - -void SwapChain11::release() -{ - SafeRelease(mSwapChain); - SafeRelease(mBackBufferTexture); - SafeRelease(mBackBufferRTView); - SafeRelease(mOffscreenTexture); - SafeRelease(mOffscreenRTView); - SafeRelease(mOffscreenSRView); - SafeRelease(mDepthStencilTexture); - SafeRelease(mDepthStencilDSView); - SafeRelease(mQuadVB); - SafeRelease(mPassThroughSampler); - SafeRelease(mPassThroughIL); - SafeRelease(mPassThroughVS); - SafeRelease(mPassThroughPS); - - if (!mAppCreatedShareHandle) - { - mShareHandle = NULL; - } -} - -void SwapChain11::releaseOffscreenTexture() -{ - SafeRelease(mOffscreenTexture); - SafeRelease(mOffscreenRTView); - SafeRelease(mOffscreenSRView); - SafeRelease(mDepthStencilTexture); - SafeRelease(mDepthStencilDSView); -} - -EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight) -{ - ID3D11Device *device = mRenderer->getDevice(); - - ASSERT(device != NULL); - - // D3D11 does not allow zero size textures - ASSERT(backbufferWidth >= 1); - ASSERT(backbufferHeight >= 1); - - // Preserve the render target content - ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture; - if (previousOffscreenTexture) - { - previousOffscreenTexture->AddRef(); - } - const int previousWidth = mWidth; - const int previousHeight = mHeight; - - releaseOffscreenTexture(); - - // If the app passed in a share handle, open the resource - // See EGL_ANGLE_d3d_share_handle_client_buffer - if (mAppCreatedShareHandle) - { - ID3D11Resource *tempResource11; - HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11); - - if (FAILED(result)) - { - ERR("Failed to open the swap chain pbuffer share handle: %08lX", result); - release(); - return EGL_BAD_PARAMETER; - } - - result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture); - tempResource11->Release(); - - if (FAILED(result)) - { - ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result); - release(); - return EGL_BAD_PARAMETER; - } - - // Validate offscreen texture parameters - D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; - mOffscreenTexture->GetDesc(&offscreenTextureDesc); - - if (offscreenTextureDesc.Width != (UINT)backbufferWidth - || offscreenTextureDesc.Height != (UINT)backbufferHeight - || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat) - || offscreenTextureDesc.MipLevels != 1 - || offscreenTextureDesc.ArraySize != 1) - { - ERR("Invalid texture parameters in the shared offscreen texture pbuffer"); - release(); - return EGL_BAD_PARAMETER; - } - } - else - { - const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport(); - - D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0}; - offscreenTextureDesc.Width = backbufferWidth; - offscreenTextureDesc.Height = backbufferHeight; - offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); - offscreenTextureDesc.MipLevels = 1; - offscreenTextureDesc.ArraySize = 1; - offscreenTextureDesc.SampleDesc.Count = 1; - offscreenTextureDesc.SampleDesc.Quality = 0; - offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT; - offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; - offscreenTextureDesc.CPUAccessFlags = 0; - offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0; - - HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture); - - if (FAILED(result)) - { - ERR("Could not create offscreen texture: %08lX", result); - release(); - - if (d3d11::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } - } - - d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture"); - - // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client - if (useSharedResource) - { - IDXGIResource *offscreenTextureResource = NULL; - result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource); - - // Fall back to no share handle on failure - if (FAILED(result)) - { - ERR("Could not query offscreen texture resource: %08lX", result); - } - else - { - result = offscreenTextureResource->GetSharedHandle(&mShareHandle); - offscreenTextureResource->Release(); - - if (FAILED(result)) - { - mShareHandle = NULL; - ERR("Could not get offscreen texture shared handle: %08lX", result); - } - } - } - } - - HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView); - - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target"); - - result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource"); - - if (mDepthBufferFormat != GL_NONE) - { - D3D11_TEXTURE2D_DESC depthStencilDesc = {0}; - depthStencilDesc.Width = backbufferWidth; - depthStencilDesc.Height = backbufferHeight; - depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat); - depthStencilDesc.MipLevels = 1; - depthStencilDesc.ArraySize = 1; - depthStencilDesc.SampleDesc.Count = 1; - depthStencilDesc.SampleDesc.Quality = 0; - depthStencilDesc.Usage = D3D11_USAGE_DEFAULT; - depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; - depthStencilDesc.CPUAccessFlags = 0; - depthStencilDesc.MiscFlags = 0; - - result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture); - if (FAILED(result)) - { - ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); - release(); - - if (d3d11::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } - } - d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture"); - - result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view"); - } - - mWidth = backbufferWidth; - mHeight = backbufferHeight; - - if (previousOffscreenTexture != NULL) - { - D3D11_BOX sourceBox = {0}; - sourceBox.left = 0; - sourceBox.right = std::min(previousWidth, mWidth); - sourceBox.top = std::max(previousHeight - mHeight, 0); - sourceBox.bottom = previousHeight; - sourceBox.front = 0; - sourceBox.back = 1; - - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - const int yoffset = std::max(mHeight - previousHeight, 0); - deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox); - - previousOffscreenTexture->Release(); - - if (mSwapChain) - { - swapRect(0, 0, mWidth, mHeight); - } - } - - return EGL_SUCCESS; -} - -EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight) -{ - ID3D11Device *device = mRenderer->getDevice(); - - if (device == NULL) - { - return EGL_BAD_ACCESS; - } - - // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains - if (backbufferWidth < 1 || backbufferHeight < 1) - { - return EGL_SUCCESS; - } - - // Can only call resize if we have already created our swap buffer and resources - ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView); - - SafeRelease(mBackBufferTexture); - SafeRelease(mBackBufferRTView); - - // Resize swap chain - DXGI_FORMAT backbufferDXGIFormat = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); - HRESULT result = mSwapChain->ResizeBuffers(2, backbufferWidth, backbufferHeight, backbufferDXGIFormat, 0); - - if (FAILED(result)) - { - ERR("Error resizing swap chain buffers: 0x%08X", result); - release(); - - if (d3d11::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } - } - - result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); - ASSERT(SUCCEEDED(result)); - if (SUCCEEDED(result)) - { - d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); - } - - result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); - ASSERT(SUCCEEDED(result)); - if (SUCCEEDED(result)) - { - d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); - } - - return resetOffscreenTexture(backbufferWidth, backbufferHeight); -} - -EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) -{ - ID3D11Device *device = mRenderer->getDevice(); - - if (device == NULL) - { - return EGL_BAD_ACCESS; - } - - // Release specific resources to free up memory for the new render target, while the - // old render target still exists for the purpose of preserving its contents. - SafeRelease(mSwapChain); - SafeRelease(mBackBufferTexture); - SafeRelease(mBackBufferRTView); - - mSwapInterval = static_cast(swapInterval); - if (mSwapInterval > 4) - { - // IDXGISwapChain::Present documentation states that valid sync intervals are in the [0,4] range - return EGL_BAD_PARAMETER; - } - - // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains - if (backbufferWidth < 1 || backbufferHeight < 1) - { - releaseOffscreenTexture(); - return EGL_SUCCESS; - } - - if (mWindow) - { -#if !defined(ANGLE_OS_WINRT) - IDXGIFactory *factory = mRenderer->getDxgiFactory(); - - DXGI_SWAP_CHAIN_DESC swapChainDesc = {0}; - swapChainDesc.BufferDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); - swapChainDesc.BufferDesc.Width = backbufferWidth; - swapChainDesc.BufferDesc.Height = backbufferHeight; - swapChainDesc.BufferCount = 2; - swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED; - swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; - swapChainDesc.BufferDesc.RefreshRate.Numerator = 0; - swapChainDesc.BufferDesc.RefreshRate.Denominator = 1; - swapChainDesc.Windowed = TRUE; - swapChainDesc.OutputWindow = mWindow; -#else - IDXGIFactory2 *factory; - HRESULT result = mRenderer->getDxgiFactory()->QueryInterface(IID_PPV_ARGS(&factory)); - ASSERT(SUCCEEDED(result)); - - DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0}; - swapChainDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat); - swapChainDesc.Width = backbufferWidth; - swapChainDesc.Height = backbufferHeight; - swapChainDesc.Stereo = FALSE; -#if !defined(ANGLE_OS_WINPHONE) - swapChainDesc.BufferCount = 2; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; -#else - swapChainDesc.BufferCount = 1; - swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; -#endif -#endif - swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swapChainDesc.Flags = 0; - swapChainDesc.SampleDesc.Count = 1; - swapChainDesc.SampleDesc.Quality = 0; - -#if !defined(ANGLE_OS_WINRT) - HRESULT result = factory->CreateSwapChain(device, &swapChainDesc, &mSwapChain); -#else - IDXGISwapChain1 *swapChain; - result = factory->CreateSwapChainForCoreWindow(device, mWindow, &swapChainDesc, NULL, &swapChain); - mSwapChain = swapChain; -#endif - - if (FAILED(result)) - { - ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); - release(); - - if (d3d11::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } -#if !defined(ANGLE_OS_WINRT) - else - { - // We cannot create a swap chain for an HWND that is owned by a different process on some versions of - // windows - DWORD currentProcessId = GetCurrentProcessId(); - DWORD wndProcessId; - GetWindowThreadProcessId(mWindow, &wndProcessId); - - if (currentProcessId != wndProcessId) - { - ERR("Could not create swap chain, window owned by different process"); - return EGL_BAD_NATIVE_WINDOW; - } - else - { - return EGL_BAD_ALLOC; - } - } -#else - return EGL_BAD_ALLOC; -#endif - } - - result = mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&mBackBufferTexture); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mBackBufferTexture, "Back buffer texture"); - - result = device->CreateRenderTargetView(mBackBufferTexture, NULL, &mBackBufferRTView); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target"); - } - - // If we are resizing the swap chain, we don't wish to recreate all the static resources - if (!mPassThroughResourcesInit) - { - mPassThroughResourcesInit = true; - initPassThroughResources(); - } - - return resetOffscreenTexture(backbufferWidth, backbufferHeight); -} - -void SwapChain11::initPassThroughResources() -{ - ID3D11Device *device = mRenderer->getDevice(); - - ASSERT(device != NULL); - - // Make sure our resources are all not allocated, when we create - ASSERT(mQuadVB == NULL && mPassThroughSampler == NULL); - ASSERT(mPassThroughIL == NULL && mPassThroughVS == NULL && mPassThroughPS == NULL); - - D3D11_BUFFER_DESC vbDesc; - vbDesc.ByteWidth = sizeof(d3d11::PositionTexCoordVertex) * 4; - vbDesc.Usage = D3D11_USAGE_DYNAMIC; - vbDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - vbDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - vbDesc.MiscFlags = 0; - vbDesc.StructureByteStride = 0; - - HRESULT result = device->CreateBuffer(&vbDesc, NULL, &mQuadVB); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mQuadVB, "Swap chain quad vertex buffer"); - - D3D11_SAMPLER_DESC samplerDesc; - samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; - samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - samplerDesc.MipLODBias = 0.0f; - samplerDesc.MaxAnisotropy = 0; - samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER; - samplerDesc.BorderColor[0] = 0.0f; - samplerDesc.BorderColor[1] = 0.0f; - samplerDesc.BorderColor[2] = 0.0f; - samplerDesc.BorderColor[3] = 0.0f; - samplerDesc.MinLOD = 0; - samplerDesc.MaxLOD = D3D11_FLOAT32_MAX; - - result = device->CreateSamplerState(&samplerDesc, &mPassThroughSampler); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughSampler, "Swap chain pass through sampler"); - - D3D11_INPUT_ELEMENT_DESC quadLayout[] = - { - { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - - result = device->CreateInputLayout(quadLayout, 2, g_VS_Passthrough, sizeof(g_VS_Passthrough), &mPassThroughIL); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughIL, "Swap chain pass through layout"); - - result = device->CreateVertexShader(g_VS_Passthrough, sizeof(g_VS_Passthrough), NULL, &mPassThroughVS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughVS, "Swap chain pass through vertex shader"); - - result = device->CreatePixelShader(g_PS_PassthroughRGBA, sizeof(g_PS_PassthroughRGBA), NULL, &mPassThroughPS); - ASSERT(SUCCEEDED(result)); - d3d11::SetDebugName(mPassThroughPS, "Swap chain pass through pixel shader"); -} - -// parameters should be validated/clamped by caller -EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) -{ - if (!mSwapChain) - { - return EGL_SUCCESS; - } - - ID3D11Device *device = mRenderer->getDevice(); - ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext(); - - // Set vertices - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - return EGL_BAD_ACCESS; - } - - d3d11::PositionTexCoordVertex *vertices = static_cast(mappedResource.pData); - - // Create a quad in homogeneous coordinates - float x1 = (x / float(mWidth)) * 2.0f - 1.0f; - float y1 = (y / float(mHeight)) * 2.0f - 1.0f; - float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f; - float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f; - - float u1 = x / float(mWidth); - float v1 = y / float(mHeight); - float u2 = (x + width) / float(mWidth); - float v2 = (y + height) / float(mHeight); - - d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1); - d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2); - d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1); - d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2); - - deviceContext->Unmap(mQuadVB, 0); - - static UINT stride = sizeof(d3d11::PositionTexCoordVertex); - static UINT startIdx = 0; - deviceContext->IASetVertexBuffers(0, 1, &mQuadVB, &stride, &startIdx); - - // Apply state - deviceContext->OMSetDepthStencilState(NULL, 0xFFFFFFFF); - - static const float blendFactor[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; - deviceContext->OMSetBlendState(NULL, blendFactor, 0xFFFFFFF); - - deviceContext->RSSetState(NULL); - - // Apply shaders - deviceContext->IASetInputLayout(mPassThroughIL); - deviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); - deviceContext->VSSetShader(mPassThroughVS, NULL, 0); - deviceContext->PSSetShader(mPassThroughPS, NULL, 0); - deviceContext->GSSetShader(NULL, NULL, 0); - - // Apply render targets - mRenderer->setOneTimeRenderTarget(mBackBufferRTView); - - // Set the viewport - D3D11_VIEWPORT viewport; - viewport.TopLeftX = 0; - viewport.TopLeftY = 0; - viewport.Width = mWidth; - viewport.Height = mHeight; - viewport.MinDepth = 0.0f; - viewport.MaxDepth = 1.0f; - deviceContext->RSSetViewports(1, &viewport); - - // Apply textures - deviceContext->PSSetShaderResources(0, 1, &mOffscreenSRView); - deviceContext->PSSetSamplers(0, 1, &mPassThroughSampler); - - // Draw - deviceContext->Draw(4, 0); - -#if ANGLE_FORCE_VSYNC_OFF - result = mSwapChain->Present(0, 0); -#else - result = mSwapChain->Present(mSwapInterval, 0); -#endif - - if (result == DXGI_ERROR_DEVICE_REMOVED) - { - HRESULT removedReason = device->GetDeviceRemovedReason(); - ERR("Present failed: the D3D11 device was removed: 0x%08X", removedReason); - return EGL_CONTEXT_LOST; - } - else if (result == DXGI_ERROR_DEVICE_RESET) - { - ERR("Present failed: the D3D11 device was reset from a bad command."); - return EGL_CONTEXT_LOST; - } - else if (FAILED(result)) - { - ERR("Present failed with error code 0x%08X", result); - } - - // Unbind - static ID3D11ShaderResourceView *const nullSRV = NULL; - deviceContext->PSSetShaderResources(0, 1, &nullSRV); - - mRenderer->unapplyRenderTargets(); - mRenderer->markAllStateDirty(); - - return EGL_SUCCESS; -} - -// Increments refcount on texture. -// caller must Release() the returned texture -ID3D11Texture2D *SwapChain11::getOffscreenTexture() -{ - if (mOffscreenTexture) - { - mOffscreenTexture->AddRef(); - } - - return mOffscreenTexture; -} - -// Increments refcount on view. -// caller must Release() the returned view -ID3D11RenderTargetView *SwapChain11::getRenderTarget() -{ - if (mOffscreenRTView) - { - mOffscreenRTView->AddRef(); - } - - return mOffscreenRTView; -} - -// Increments refcount on view. -// caller must Release() the returned view -ID3D11ShaderResourceView *SwapChain11::getRenderTargetShaderResource() -{ - if (mOffscreenSRView) - { - mOffscreenSRView->AddRef(); - } - - return mOffscreenSRView; -} - -// Increments refcount on view. -// caller must Release() the returned view -ID3D11DepthStencilView *SwapChain11::getDepthStencil() -{ - if (mDepthStencilDSView) - { - mDepthStencilDSView->AddRef(); - } - - return mDepthStencilDSView; -} - -ID3D11Texture2D *SwapChain11::getDepthStencilTexture() -{ - if (mDepthStencilTexture) - { - mDepthStencilTexture->AddRef(); - } - - return mDepthStencilTexture; -} - -SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain11*, swapChain)); - return static_cast(swapChain); -} - -void SwapChain11::recreate() -{ - // possibly should use this method instead of reset -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h deleted file mode 100644 index 2a030c839d..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/SwapChain11.h +++ /dev/null @@ -1,78 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// SwapChain11.h: Defines a back-end specific class for the D3D11 swap chain. - -#ifndef LIBGLESV2_RENDERER_SWAPCHAIN11_H_ -#define LIBGLESV2_RENDERER_SWAPCHAIN11_H_ - -#include "common/angleutils.h" -#include "libGLESv2/renderer/SwapChain.h" - -namespace rx -{ -class Renderer11; - -class SwapChain11 : public SwapChain -{ - public: - SwapChain11(Renderer11 *renderer, EGLNativeWindowType window, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat); - virtual ~SwapChain11(); - - EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); - virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); - virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); - virtual void recreate(); - - virtual ID3D11Texture2D *getOffscreenTexture(); - virtual ID3D11RenderTargetView *getRenderTarget(); - virtual ID3D11ShaderResourceView *getRenderTargetShaderResource(); - - virtual ID3D11Texture2D *getDepthStencilTexture(); - virtual ID3D11DepthStencilView *getDepthStencil(); - - EGLint getWidth() const { return mWidth; } - EGLint getHeight() const { return mHeight; } - - static SwapChain11 *makeSwapChain11(SwapChain *swapChain); - - private: - DISALLOW_COPY_AND_ASSIGN(SwapChain11); - - void release(); - void initPassThroughResources(); - void releaseOffscreenTexture(); - EGLint resetOffscreenTexture(int backbufferWidth, int backbufferHeight); - - Renderer11 *mRenderer; - EGLint mHeight; - EGLint mWidth; - bool mAppCreatedShareHandle; - unsigned int mSwapInterval; - bool mPassThroughResourcesInit; - - IDXGISwapChain *mSwapChain; - - ID3D11Texture2D *mBackBufferTexture; - ID3D11RenderTargetView *mBackBufferRTView; - - ID3D11Texture2D *mOffscreenTexture; - ID3D11RenderTargetView *mOffscreenRTView; - ID3D11ShaderResourceView *mOffscreenSRView; - - ID3D11Texture2D *mDepthStencilTexture; - ID3D11DepthStencilView *mDepthStencilDSView; - - ID3D11Buffer *mQuadVB; - ID3D11SamplerState *mPassThroughSampler; - ID3D11InputLayout *mPassThroughIL; - ID3D11VertexShader *mPassThroughVS; - ID3D11PixelShader *mPassThroughPS; -}; - -} -#endif // LIBGLESV2_RENDERER_SWAPCHAIN11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp deleted file mode 100644 index 0c981ac503..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.cpp +++ /dev/null @@ -1,667 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TextureStorage11.cpp: Implements the abstract rx::TextureStorage11 class and its concrete derived -// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. - -#include "libGLESv2/renderer/d3d11/TextureStorage11.h" - -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/renderer/d3d11/RenderTarget11.h" -#include "libGLESv2/renderer/d3d11/SwapChain11.h" -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" - -#include "libGLESv2/utilities.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -TextureStorage11::TextureStorage11(Renderer *renderer, UINT bindFlags) - : mBindFlags(bindFlags), - mLodOffset(0), - mMipLevels(0), - mTexture(NULL), - mTextureFormat(DXGI_FORMAT_UNKNOWN), - mShaderResourceFormat(DXGI_FORMAT_UNKNOWN), - mRenderTargetFormat(DXGI_FORMAT_UNKNOWN), - mDepthStencilFormat(DXGI_FORMAT_UNKNOWN), - mSRV(NULL), - mTextureWidth(0), - mTextureHeight(0) -{ - mRenderer = Renderer11::makeRenderer11(renderer); -} - -TextureStorage11::~TextureStorage11() -{ -} - -TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11*, storage)); - return static_cast(storage); -} - -DWORD TextureStorage11::GetTextureBindFlags(DXGI_FORMAT format, GLenum glusage, bool forceRenderable) -{ - UINT bindFlags = D3D11_BIND_SHADER_RESOURCE; - - if (d3d11::IsDepthStencilFormat(format)) - { - bindFlags |= D3D11_BIND_DEPTH_STENCIL; - } - else if(forceRenderable || (TextureStorage11::IsTextureFormatRenderable(format) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE))) - { - bindFlags |= D3D11_BIND_RENDER_TARGET; - } - return bindFlags; -} - -bool TextureStorage11::IsTextureFormatRenderable(DXGI_FORMAT format) -{ - switch(format) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - case DXGI_FORMAT_A8_UNORM: - case DXGI_FORMAT_R32G32B32A32_FLOAT: - case DXGI_FORMAT_R16G16B16A16_FLOAT: - case DXGI_FORMAT_B8G8R8A8_UNORM: - case DXGI_FORMAT_R8_UNORM: - case DXGI_FORMAT_R8G8_UNORM: - case DXGI_FORMAT_R16_FLOAT: - case DXGI_FORMAT_R16G16_FLOAT: - return true; - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_R32G32B32_FLOAT: // not renderable on all devices - return false; - default: - UNREACHABLE(); - return false; - } -} - -UINT TextureStorage11::getBindFlags() const -{ - return mBindFlags; -} - -ID3D11Texture2D *TextureStorage11::getBaseTexture() const -{ - return mTexture; -} - -int TextureStorage11::getLodOffset() const -{ - return mLodOffset; -} - -bool TextureStorage11::isRenderTarget() const -{ - return (mBindFlags & (D3D11_BIND_RENDER_TARGET | D3D11_BIND_DEPTH_STENCIL)) != 0; -} - -bool TextureStorage11::isManaged() const -{ - return false; -} - -int TextureStorage11::levelCount() -{ - int levels = 0; - if (getBaseTexture()) - { - levels = mMipLevels - getLodOffset(); - } - return levels; -} - -UINT TextureStorage11::getSubresourceIndex(int level, int faceIndex) -{ - UINT index = 0; - if (getBaseTexture()) - { - index = D3D11CalcSubresource(level, faceIndex, mMipLevels); - } - return index; -} - -bool TextureStorage11::updateSubresourceLevel(ID3D11Texture2D *srcTexture, unsigned int sourceSubresource, - int level, int face, GLint xoffset, GLint yoffset, - GLsizei width, GLsizei height) -{ - if (srcTexture) - { - // Round up the width and height to the nearest multiple of dimension alignment - unsigned int dimensionAlignment = d3d11::GetTextureFormatDimensionAlignment(mTextureFormat); - width = width + dimensionAlignment - 1 - (width - 1) % dimensionAlignment; - height = height + dimensionAlignment - 1 - (height - 1) % dimensionAlignment; - - D3D11_BOX srcBox; - srcBox.left = xoffset; - srcBox.top = yoffset; - srcBox.right = xoffset + width; - srcBox.bottom = yoffset + height; - srcBox.front = 0; - srcBox.back = 1; - - ID3D11DeviceContext *context = mRenderer->getDeviceContext(); - - ASSERT(getBaseTexture()); - context->CopySubresourceRegion(getBaseTexture(), getSubresourceIndex(level + mLodOffset, face), - xoffset, yoffset, 0, srcTexture, sourceSubresource, &srcBox); - return true; - } - - return false; -} - -void TextureStorage11::generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest) -{ - if (source && dest) - { - ID3D11ShaderResourceView *sourceSRV = source->getShaderResourceView(); - ID3D11RenderTargetView *destRTV = dest->getRenderTargetView(); - - if (sourceSRV && destRTV) - { - gl::Rectangle sourceArea; - sourceArea.x = 0; - sourceArea.y = 0; - sourceArea.width = source->getWidth(); - sourceArea.height = source->getHeight(); - - gl::Rectangle destArea; - destArea.x = 0; - destArea.y = 0; - destArea.width = dest->getWidth(); - destArea.height = dest->getHeight(); - - mRenderer->copyTexture(sourceSRV, sourceArea, source->getWidth(), source->getHeight(), - destRTV, destArea, dest->getWidth(), dest->getHeight(), - GL_RGBA); - } - } -} - -TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain) - : TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE) -{ - mTexture = swapchain->getOffscreenTexture(); - mSRV = swapchain->getRenderTargetShaderResource(); - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mRenderTarget[i] = NULL; - } - - D3D11_TEXTURE2D_DESC texDesc; - mTexture->GetDesc(&texDesc); - mMipLevels = texDesc.MipLevels; - mTextureFormat = texDesc.Format; - mTextureWidth = texDesc.Width; - mTextureHeight = texDesc.Height; - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - mSRV->GetDesc(&srvDesc); - mShaderResourceFormat = srvDesc.Format; - - ID3D11RenderTargetView* offscreenRTV = swapchain->getRenderTarget(); - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - offscreenRTV->GetDesc(&rtvDesc); - mRenderTargetFormat = rtvDesc.Format; - offscreenRTV->Release(); - - mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; -} - -TextureStorage11_2D::TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) - : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()), usage, forceRenderable)) -{ - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - mRenderTarget[i] = NULL; - } - - DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel()); - if (d3d11::IsDepthStencilFormat(convertedFormat)) - { - mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); - mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat); - mDepthStencilFormat = convertedFormat; - mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; - } - else - { - mTextureFormat = convertedFormat; - mShaderResourceFormat = convertedFormat; - mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; - mRenderTargetFormat = convertedFormat; - } - - // if the width or height is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (width > 0 && height > 0) - { - // adjust size if needed for compressed textures - gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset); - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = width; // Compressed texture size constraints? - desc.Height = height; - desc.MipLevels = mRenderer->getFeatureLevel() >= D3D_FEATURE_LEVEL_10_0 ? ((levels > 0) ? levels + mLodOffset : 0) : 1; - desc.ArraySize = 1; - desc.Format = mTextureFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = getBindFlags(); - desc.CPUAccessFlags = 0; - desc.MiscFlags = 0; - - HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); - - // this can happen from windows TDR - if (d3d11::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - gl::error(GL_OUT_OF_MEMORY); - } - else if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - ERR("Creating image failed."); - gl::error(GL_OUT_OF_MEMORY); - } - else - { - mTexture->GetDesc(&desc); - mMipLevels = desc.MipLevels; - mTextureWidth = desc.Width; - mTextureHeight = desc.Height; - } - } -} - -TextureStorage11_2D::~TextureStorage11_2D() -{ - if (mTexture) - { - mTexture->Release(); - mTexture = NULL; - } - - if (mSRV) - { - mSRV->Release(); - mSRV = NULL; - } - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++) - { - delete mRenderTarget[i]; - mRenderTarget[i] = NULL; - } -} - -TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_2D*, storage)); - return static_cast(storage); -} - -RenderTarget *TextureStorage11_2D::getRenderTarget(int level) -{ - if (level >= 0 && level < static_cast(mMipLevels)) - { - if (!mRenderTarget[level]) - { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MostDetailedMip = level; - srvDesc.Texture2D.MipLevels = level ? 1 : -1; - - ID3D11ShaderResourceView *srv; - result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - rtvDesc.Texture2D.MipSlice = level; - - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); - - if (result == E_OUTOFMEMORY) - { - srv->Release(); - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 - // also needs to keep a reference to the texture. - mTexture->AddRef(); - - mRenderTarget[level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, - std::max(mTextureWidth >> level, 1U), - std::max(mTextureHeight >> level, 1U)); - } - else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = mDepthStencilFormat; - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; - dsvDesc.Texture2D.MipSlice = level; - dsvDesc.Flags = 0; - - ID3D11DepthStencilView *dsv; - result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); - - if (result == E_OUTOFMEMORY) - { - srv->Release(); - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 - // also needs to keep a reference to the texture. - mTexture->AddRef(); - - mRenderTarget[level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, - std::max(mTextureWidth >> level, 1U), - std::max(mTextureHeight >> level, 1U)); - } - else - { - UNREACHABLE(); - } - } - - return mRenderTarget[level]; - } - else - { - return NULL; - } -} - -ID3D11ShaderResourceView *TextureStorage11_2D::getSRV() -{ - if (!mSRV) - { - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srvDesc.Texture2D.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels); - srvDesc.Texture2D.MostDetailedMip = 0; - - HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - } - - return mSRV; -} - -void TextureStorage11_2D::generateMipmap(int level) -{ - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(level - 1)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(level)); - - generateMipmapLayer(source, dest); -} - -TextureStorage11_Cube::TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) - : TextureStorage11(renderer, GetTextureBindFlags(gl_d3d11::ConvertTextureFormat(internalformat, Renderer11::makeRenderer11(renderer)->getFeatureLevel()), usage, forceRenderable)) -{ - for (unsigned int i = 0; i < 6; i++) - { - for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++) - { - mRenderTarget[i][j] = NULL; - } - } - - DXGI_FORMAT convertedFormat = gl_d3d11::ConvertTextureFormat(internalformat, mRenderer->getFeatureLevel()); - if (d3d11::IsDepthStencilFormat(convertedFormat)) - { - mTextureFormat = d3d11::GetDepthTextureFormat(convertedFormat); - mShaderResourceFormat = d3d11::GetDepthShaderResourceFormat(convertedFormat); - mDepthStencilFormat = convertedFormat; - mRenderTargetFormat = DXGI_FORMAT_UNKNOWN; - } - else - { - mTextureFormat = convertedFormat; - mShaderResourceFormat = convertedFormat; - mDepthStencilFormat = DXGI_FORMAT_UNKNOWN; - mRenderTargetFormat = convertedFormat; - } - - // if the size is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (size > 0) - { - // adjust size if needed for compressed textures - int height = size; - gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset); - - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_TEXTURE2D_DESC desc; - desc.Width = size; - desc.Height = size; - desc.MipLevels = (levels > 0) ? levels + mLodOffset : 0; - desc.ArraySize = 6; - desc.Format = mTextureFormat; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = getBindFlags(); - desc.CPUAccessFlags = 0; - desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE; - - HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture); - - if (FAILED(result)) - { - ASSERT(result == E_OUTOFMEMORY); - ERR("Creating image failed."); - gl::error(GL_OUT_OF_MEMORY); - } - else - { - mTexture->GetDesc(&desc); - mMipLevels = desc.MipLevels; - mTextureWidth = desc.Width; - mTextureHeight = desc.Height; - } - } -} - -TextureStorage11_Cube::~TextureStorage11_Cube() -{ - if (mTexture) - { - mTexture->Release(); - mTexture = NULL; - } - - if (mSRV) - { - mSRV->Release(); - mSRV = NULL; - } - - for (unsigned int i = 0; i < 6; i++) - { - for (unsigned int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; j++) - { - delete mRenderTarget[i][j]; - mRenderTarget[i][j] = NULL; - } - } -} - -TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage11_Cube*, storage)); - return static_cast(storage); -} - -RenderTarget *TextureStorage11_Cube::getRenderTarget(GLenum faceTarget, int level) -{ - unsigned int faceIdx = gl::TextureCubeMap::faceIndex(faceTarget); - if (level >= 0 && level < static_cast(mMipLevels)) - { - if (!mRenderTarget[faceIdx][level]) - { - ID3D11Device *device = mRenderer->getDevice(); - HRESULT result; - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube - srvDesc.Texture2DArray.MostDetailedMip = level; - srvDesc.Texture2DArray.MipLevels = 1; - srvDesc.Texture2DArray.FirstArraySlice = faceIdx; - srvDesc.Texture2DArray.ArraySize = 1; - - ID3D11ShaderResourceView *srv; - result = device->CreateShaderResourceView(mTexture, &srvDesc, &srv); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_RENDER_TARGET_VIEW_DESC rtvDesc; - rtvDesc.Format = mRenderTargetFormat; - rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY; - rtvDesc.Texture2DArray.MipSlice = level; - rtvDesc.Texture2DArray.FirstArraySlice = faceIdx; - rtvDesc.Texture2DArray.ArraySize = 1; - - ID3D11RenderTargetView *rtv; - result = device->CreateRenderTargetView(mTexture, &rtvDesc, &rtv); - - if (result == E_OUTOFMEMORY) - { - srv->Release(); - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 - // also needs to keep a reference to the texture. - mTexture->AddRef(); - - mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, rtv, mTexture, srv, - std::max(mTextureWidth >> level, 1U), - std::max(mTextureHeight >> level, 1U)); - } - else if (mDepthStencilFormat != DXGI_FORMAT_UNKNOWN) - { - D3D11_DEPTH_STENCIL_VIEW_DESC dsvDesc; - dsvDesc.Format = mRenderTargetFormat; - dsvDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2DARRAY; - dsvDesc.Texture2DArray.MipSlice = level; - dsvDesc.Texture2DArray.FirstArraySlice = faceIdx; - dsvDesc.Texture2DArray.ArraySize = 1; - - ID3D11DepthStencilView *dsv; - result = device->CreateDepthStencilView(mTexture, &dsvDesc, &dsv); - - if (result == E_OUTOFMEMORY) - { - srv->Release(); - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - - // RenderTarget11 expects to be the owner of the resources it is given but TextureStorage11 - // also needs to keep a reference to the texture. - mTexture->AddRef(); - - mRenderTarget[faceIdx][level] = new RenderTarget11(mRenderer, dsv, mTexture, srv, - std::max(mTextureWidth >> level, 1U), - std::max(mTextureHeight >> level, 1U)); - } - else - { - UNREACHABLE(); - } - } - - return mRenderTarget[faceIdx][level]; - } - else - { - return NULL; - } -} - -ID3D11ShaderResourceView *TextureStorage11_Cube::getSRV() -{ - if (!mSRV) - { - ID3D11Device *device = mRenderer->getDevice(); - - D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; - srvDesc.Format = mShaderResourceFormat; - srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; - srvDesc.TextureCube.MipLevels = (mMipLevels == 0 ? -1 : mMipLevels); - srvDesc.TextureCube.MostDetailedMip = 0; - - HRESULT result = device->CreateShaderResourceView(mTexture, &srvDesc, &mSRV); - - if (result == E_OUTOFMEMORY) - { - return gl::error(GL_OUT_OF_MEMORY, static_cast(NULL)); - } - ASSERT(SUCCEEDED(result)); - } - - return mSRV; -} - -void TextureStorage11_Cube::generateMipmap(int face, int level) -{ - RenderTarget11 *source = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1)); - RenderTarget11 *dest = RenderTarget11::makeRenderTarget11(getRenderTarget(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level)); - - generateMipmapLayer(source, dest); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h deleted file mode 100644 index 3c5ded05b8..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/TextureStorage11.h +++ /dev/null @@ -1,120 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TextureStorage11.h: Defines the abstract rx::TextureStorage11 class and its concrete derived -// classes TextureStorage11_2D and TextureStorage11_Cube, which act as the interface to the D3D11 texture. - -#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ -#define LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ - -#include "libGLESv2/Texture.h" -#include "libGLESv2/renderer/TextureStorage.h" - -namespace rx -{ -class RenderTarget; -class RenderTarget11; -class Renderer; -class Renderer11; -class SwapChain11; - -class TextureStorage11 : public TextureStorage -{ - public: - TextureStorage11(Renderer *renderer, UINT bindFlags); - virtual ~TextureStorage11(); - - static TextureStorage11 *makeTextureStorage11(TextureStorage *storage); - - static DWORD GetTextureBindFlags(DXGI_FORMAT d3dfmt, GLenum glusage, bool forceRenderable); - static bool IsTextureFormatRenderable(DXGI_FORMAT format); - - UINT getBindFlags() const; - - virtual ID3D11Texture2D *getBaseTexture() const; - virtual ID3D11ShaderResourceView *getSRV() = 0; - virtual RenderTarget *getRenderTarget() { return getRenderTarget(0); } - virtual RenderTarget *getRenderTarget(int level) { return NULL; } - virtual RenderTarget *getRenderTarget(GLenum faceTarget) { return getRenderTarget(faceTarget, 0); } - virtual RenderTarget *getRenderTarget(GLenum faceTarget, int level) { return NULL; } - - virtual void generateMipmap(int level) {}; - virtual void generateMipmap(int face, int level) {}; - - virtual int getLodOffset() const; - virtual bool isRenderTarget() const; - virtual bool isManaged() const; - virtual int levelCount(); - UINT getSubresourceIndex(int level, int faceTarget); - - bool updateSubresourceLevel(ID3D11Texture2D *texture, unsigned int sourceSubresource, int level, - int faceTarget, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - - protected: - void generateMipmapLayer(RenderTarget11 *source, RenderTarget11 *dest); - - Renderer11 *mRenderer; - int mLodOffset; - unsigned int mMipLevels; - - ID3D11Texture2D *mTexture; - DXGI_FORMAT mTextureFormat; - DXGI_FORMAT mShaderResourceFormat; - DXGI_FORMAT mRenderTargetFormat; - DXGI_FORMAT mDepthStencilFormat; - unsigned int mTextureWidth; - unsigned int mTextureHeight; - - ID3D11ShaderResourceView *mSRV; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11); - - const UINT mBindFlags; -}; - -class TextureStorage11_2D : public TextureStorage11 -{ - public: - TextureStorage11_2D(Renderer *renderer, SwapChain11 *swapchain); - TextureStorage11_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); - virtual ~TextureStorage11_2D(); - - static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage); - - virtual ID3D11ShaderResourceView *getSRV(); - virtual RenderTarget *getRenderTarget(int level); - - virtual void generateMipmap(int level); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D); - - RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; -}; - -class TextureStorage11_Cube : public TextureStorage11 -{ - public: - TextureStorage11_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); - virtual ~TextureStorage11_Cube(); - - static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage); - - virtual ID3D11ShaderResourceView *getSRV(); - virtual RenderTarget *getRenderTarget(GLenum faceTarget, int level); - - virtual void generateMipmap(int face, int level); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube); - - RenderTarget11 *mRenderTarget[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS]; -}; - -} - -#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp deleted file mode 100644 index 6f9b4181f1..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.cpp +++ /dev/null @@ -1,440 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation. - -#include "libGLESv2/renderer/d3d11/VertexBuffer11.h" -#include "libGLESv2/renderer/BufferStorage.h" - -#include "libGLESv2/Buffer.h" -#include "libGLESv2/renderer/d3d11/Renderer11.h" -#include "libGLESv2/Context.h" - -namespace rx -{ - -VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer) -{ - mBuffer = NULL; - mBufferSize = 0; - mDynamicUsage = false; -} - -VertexBuffer11::~VertexBuffer11() -{ - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - } -} - -bool VertexBuffer11::initialize(unsigned int size, bool dynamicUsage) -{ - if (mBuffer) - { - mBuffer->Release(); - mBuffer = NULL; - } - - updateSerial(); - - if (size > 0) - { - ID3D11Device* dxDevice = mRenderer->getDevice(); - - D3D11_BUFFER_DESC bufferDesc; - bufferDesc.ByteWidth = size; - bufferDesc.Usage = D3D11_USAGE_DYNAMIC; - bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - bufferDesc.MiscFlags = 0; - bufferDesc.StructureByteStride = 0; - - HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer); - if (FAILED(result)) - { - return false; - } - } - - mBufferSize = size; - mDynamicUsage = dynamicUsage; - return true; -} - -VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer)); - return static_cast(vetexBuffer); -} - -bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, - GLsizei instances, unsigned int offset) -{ - if (mBuffer) - { - gl::Buffer *buffer = attrib.mBoundBuffer.get(); - - int inputStride = attrib.stride(); - const VertexConverter &converter = getVertexConversion(attrib); - - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Vertex buffer map failed with error 0x%08x", result); - return false; - } - - char* output = reinterpret_cast(mappedResource.pData) + offset; - - const char *input = NULL; - if (buffer) - { - BufferStorage *storage = buffer->getStorage(); - input = static_cast(storage->getData()) + static_cast(attrib.mOffset); - } - else - { - input = static_cast(attrib.mPointer); - } - - if (instances == 0 || attrib.mDivisor == 0) - { - input += inputStride * start; - } - - converter.conversionFunc(input, inputStride, count, output); - - dxContext->Unmap(mBuffer, 0); - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -bool VertexBuffer11::storeRawData(const void* data, unsigned int size, unsigned int offset) -{ - if (mBuffer) - { - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Vertex buffer map failed with error 0x%08x", result); - return false; - } - - char* bufferData = static_cast(mappedResource.pData); - memcpy(bufferData + offset, data, size); - - dxContext->Unmap(mBuffer, 0); - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -bool VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, - GLsizei instances, unsigned int *outSpaceRequired) const -{ - unsigned int elementSize = getVertexConversion(attrib).outputElementSize; - - unsigned int elementCount = 0; - if (instances == 0 || attrib.mDivisor == 0) - { - elementCount = count; - } - else - { - if (static_cast(instances) < std::numeric_limits::max() - (attrib.mDivisor - 1)) - { - // Round up - elementCount = (static_cast(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor; - } - else - { - elementCount = instances / attrib.mDivisor; - } - } - - if (elementSize <= std::numeric_limits::max() / elementCount) - { - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * elementCount; - } - return true; - } - else - { - return false; - } -} - -bool VertexBuffer11::requiresConversion(const gl::VertexAttribute &attrib) const -{ - return !getVertexConversion(attrib).identity; -} - -unsigned int VertexBuffer11::getBufferSize() const -{ - return mBufferSize; -} - -bool VertexBuffer11::setBufferSize(unsigned int size) -{ - if (size > mBufferSize) - { - return initialize(size, mDynamicUsage); - } - else - { - return true; - } -} - -bool VertexBuffer11::discard() -{ - if (mBuffer) - { - ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext(); - - D3D11_MAPPED_SUBRESOURCE mappedResource; - HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource); - if (FAILED(result)) - { - ERR("Vertex buffer map failed with error 0x%08x", result); - return false; - } - - dxContext->Unmap(mBuffer, 0); - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -unsigned int VertexBuffer11::getVertexSize(const gl::VertexAttribute &attrib) const -{ - return getVertexConversion(attrib).outputElementSize; -} - -DXGI_FORMAT VertexBuffer11::getDXGIFormat(const gl::VertexAttribute &attrib) const -{ - return getVertexConversion(attrib).dxgiFormat; -} - -ID3D11Buffer *VertexBuffer11::getBuffer() const -{ - return mBuffer; -} - -template -static void copyVertexData(const void *input, unsigned int stride, unsigned int count, void *output) -{ - unsigned int attribSize = sizeof(T) * componentCount; - - if (attribSize == stride && !widen) - { - memcpy(output, input, count * attribSize); - } - else - { - unsigned int outputStride = widen ? 4 : componentCount; - T defaultVal = normalized ? std::numeric_limits::max() : T(1); - - for (unsigned int i = 0; i < count; i++) - { - const T *offsetInput = reinterpret_cast(reinterpret_cast(input) + i * stride); - T *offsetOutput = reinterpret_cast(output) + i * outputStride; - - for (unsigned int j = 0; j < componentCount; j++) - { - offsetOutput[j] = offsetInput[j]; - } - - if (widen) - { - offsetOutput[3] = defaultVal; - } - } - } -} - -template -static void copyFixedVertexData(const void* input, unsigned int stride, unsigned int count, void* output) -{ - static const float divisor = 1.0f / (1 << 16); - - for (unsigned int i = 0; i < count; i++) - { - const GLfixed* offsetInput = reinterpret_cast(reinterpret_cast(input) + stride * i); - float* offsetOutput = reinterpret_cast(output) + i * componentCount; - - for (unsigned int j = 0; j < componentCount; j++) - { - offsetOutput[j] = static_cast(offsetInput[j]) * divisor; - } - } -} - -template -static void copyToFloatVertexData(const void* input, unsigned int stride, unsigned int count, void* output) -{ - typedef std::numeric_limits NL; - - for (unsigned int i = 0; i < count; i++) - { - const T *offsetInput = reinterpret_cast(reinterpret_cast(input) + stride * i); - float *offsetOutput = reinterpret_cast(output) + i * componentCount; - - for (unsigned int j = 0; j < componentCount; j++) - { - if (normalized) - { - if (NL::is_signed) - { - const float divisor = 1.0f / (2 * static_cast(NL::max()) + 1); - offsetOutput[j] = (2 * static_cast(offsetInput[j]) + 1) * divisor; - } - else - { - offsetOutput[j] = static_cast(offsetInput[j]) / NL::max(); - } - } - else - { - offsetOutput[j] = static_cast(offsetInput[j]); - } - } - } -} - -const VertexBuffer11::VertexConverter VertexBuffer11::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = -{ - { // GL_BYTE - { // unnormalized - { ©ToFloatVertexData, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©VertexData, true, DXGI_FORMAT_R8_SNORM, 1 }, - { ©VertexData, true, DXGI_FORMAT_R8G8_SNORM, 2 }, - { ©VertexData, false, DXGI_FORMAT_R8G8B8A8_SNORM, 4 }, - { ©VertexData, true, DXGI_FORMAT_R8G8B8A8_SNORM, 4 }, - }, - }, - { // GL_UNSIGNED_BYTE - { // unnormalized - { ©ToFloatVertexData, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©VertexData, true, DXGI_FORMAT_R8_UNORM, 1 }, - { ©VertexData, true, DXGI_FORMAT_R8G8_UNORM, 2 }, - { ©VertexData, false, DXGI_FORMAT_R8G8B8A8_UNORM, 4 }, - { ©VertexData, true, DXGI_FORMAT_R8G8B8A8_UNORM, 4 }, - }, - }, - { // GL_SHORT - { // unnormalized - { ©ToFloatVertexData, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©VertexData, true, DXGI_FORMAT_R16_SNORM, 2 }, - { ©VertexData, true, DXGI_FORMAT_R16G16_SNORM, 4 }, - { ©VertexData, false, DXGI_FORMAT_R16G16B16A16_SNORM, 8 }, - { ©VertexData, true, DXGI_FORMAT_R16G16B16A16_SNORM, 8 }, - }, - }, - { // GL_UNSIGNED_SHORT - { // unnormalized - { ©ToFloatVertexData, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©ToFloatVertexData, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©VertexData, true, DXGI_FORMAT_R16_UNORM, 2 }, - { ©VertexData, true, DXGI_FORMAT_R16G16_UNORM, 4 }, - { ©VertexData, false, DXGI_FORMAT_R16G16B16A16_UNORM, 8 }, - { ©VertexData, true, DXGI_FORMAT_R16G16B16A16_UNORM, 8 }, - }, - }, - { // GL_FIXED - { // unnormalized - { ©FixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©FixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©FixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©FixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©FixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©FixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©FixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©FixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - }, - { // GL_FLOAT - { // unnormalized - { ©VertexData, true, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©VertexData, true, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©VertexData, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©VertexData, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - { // normalized - { ©VertexData, true, DXGI_FORMAT_R32_FLOAT, 4 }, - { ©VertexData, true, DXGI_FORMAT_R32G32_FLOAT, 8 }, - { ©VertexData, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 }, - { ©VertexData, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 }, - }, - }, -}; - -const VertexBuffer11::VertexConverter &VertexBuffer11::getVertexConversion(const gl::VertexAttribute &attribute) -{ - unsigned int typeIndex = 0; - switch (attribute.mType) - { - case GL_BYTE: typeIndex = 0; break; - case GL_UNSIGNED_BYTE: typeIndex = 1; break; - case GL_SHORT: typeIndex = 2; break; - case GL_UNSIGNED_SHORT: typeIndex = 3; break; - case GL_FIXED: typeIndex = 4; break; - case GL_FLOAT: typeIndex = 5; break; - default: UNREACHABLE(); break; - } - - return mPossibleTranslations[typeIndex][attribute.mNormalized ? 1 : 0][attribute.mSize - 1]; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h deleted file mode 100644 index eceb426e82..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/VertexBuffer11.h +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexBuffer11.h: Defines the D3D11 VertexBuffer implementation. - -#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ -#define LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ - -#include "libGLESv2/renderer/VertexBuffer.h" - -namespace rx -{ -class Renderer11; - -class VertexBuffer11 : public VertexBuffer -{ - public: - explicit VertexBuffer11(rx::Renderer11 *const renderer); - virtual ~VertexBuffer11(); - - virtual bool initialize(unsigned int size, bool dynamicUsage); - - static VertexBuffer11 *makeVertexBuffer11(VertexBuffer *vetexBuffer); - - virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, - unsigned int offset); - virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset); - - virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, - unsigned int *outSpaceRequired) const; - - virtual bool requiresConversion(const gl::VertexAttribute &attrib) const; - - virtual unsigned int getBufferSize() const; - virtual bool setBufferSize(unsigned int size); - virtual bool discard(); - - unsigned int getVertexSize(const gl::VertexAttribute &attrib) const; - DXGI_FORMAT getDXGIFormat(const gl::VertexAttribute &attrib) const; - - ID3D11Buffer *getBuffer() const; - - private: - DISALLOW_COPY_AND_ASSIGN(VertexBuffer11); - - rx::Renderer11 *const mRenderer; - - ID3D11Buffer *mBuffer; - unsigned int mBufferSize; - bool mDynamicUsage; - - typedef void (*VertexConversionFunction)(const void *, unsigned int, unsigned int, void *); - struct VertexConverter - { - VertexConversionFunction conversionFunc; - bool identity; - DXGI_FORMAT dxgiFormat; - unsigned int outputElementSize; - }; - - enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; - - // This table is used to generate mAttributeTypes. - static const VertexConverter mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; // [GL types as enumerated by typeIndex()][normalized][size - 1] - - static const VertexConverter &getVertexConversion(const gl::VertexAttribute &attribute); -}; - -} - -#endif // LIBGLESV2_RENDERER_VERTEXBUFFER11_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp deleted file mode 100644 index 34b8259a80..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.cpp +++ /dev/null @@ -1,688 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// renderer11_utils.cpp: Conversion functions and other utility routines -// specific to the D3D11 renderer. - -#include "libGLESv2/renderer/d3d11/renderer11_utils.h" - -#include "common/debug.h" - -namespace gl_d3d11 -{ - -D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha) -{ - D3D11_BLEND d3dBlend = D3D11_BLEND_ZERO; - - switch (glBlend) - { - case GL_ZERO: d3dBlend = D3D11_BLEND_ZERO; break; - case GL_ONE: d3dBlend = D3D11_BLEND_ONE; break; - case GL_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_SRC_ALPHA : D3D11_BLEND_SRC_COLOR); break; - case GL_ONE_MINUS_SRC_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_SRC_ALPHA : D3D11_BLEND_INV_SRC_COLOR); break; - case GL_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_DEST_ALPHA : D3D11_BLEND_DEST_COLOR); break; - case GL_ONE_MINUS_DST_COLOR: d3dBlend = (isAlpha ? D3D11_BLEND_INV_DEST_ALPHA : D3D11_BLEND_INV_DEST_COLOR); break; - case GL_SRC_ALPHA: d3dBlend = D3D11_BLEND_SRC_ALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3D11_BLEND_INV_SRC_ALPHA; break; - case GL_DST_ALPHA: d3dBlend = D3D11_BLEND_DEST_ALPHA; break; - case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3D11_BLEND_INV_DEST_ALPHA; break; - case GL_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break; - case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break; - case GL_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_BLEND_FACTOR; break; - case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3D11_BLEND_INV_BLEND_FACTOR; break; - case GL_SRC_ALPHA_SATURATE: d3dBlend = D3D11_BLEND_SRC_ALPHA_SAT; break; - default: UNREACHABLE(); - } - - return d3dBlend; -} - -D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp) -{ - D3D11_BLEND_OP d3dBlendOp = D3D11_BLEND_OP_ADD; - - switch (glBlendOp) - { - case GL_FUNC_ADD: d3dBlendOp = D3D11_BLEND_OP_ADD; break; - case GL_FUNC_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_SUBTRACT; break; - case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3D11_BLEND_OP_REV_SUBTRACT; break; - default: UNREACHABLE(); - } - - return d3dBlendOp; -} - -UINT8 ConvertColorMask(bool red, bool green, bool blue, bool alpha) -{ - UINT8 mask = 0; - if (red) - { - mask |= D3D11_COLOR_WRITE_ENABLE_RED; - } - if (green) - { - mask |= D3D11_COLOR_WRITE_ENABLE_GREEN; - } - if (blue) - { - mask |= D3D11_COLOR_WRITE_ENABLE_BLUE; - } - if (alpha) - { - mask |= D3D11_COLOR_WRITE_ENABLE_ALPHA; - } - return mask; -} - -D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode) -{ - D3D11_CULL_MODE cull = D3D11_CULL_NONE; - - if (cullEnabled) - { - switch (cullMode) - { - case GL_FRONT: cull = D3D11_CULL_FRONT; break; - case GL_BACK: cull = D3D11_CULL_BACK; break; - case GL_FRONT_AND_BACK: cull = D3D11_CULL_NONE; break; - default: UNREACHABLE(); - } - } - else - { - cull = D3D11_CULL_NONE; - } - - return cull; -} - -D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison) -{ - D3D11_COMPARISON_FUNC d3dComp = D3D11_COMPARISON_NEVER; - switch (comparison) - { - case GL_NEVER: d3dComp = D3D11_COMPARISON_NEVER; break; - case GL_ALWAYS: d3dComp = D3D11_COMPARISON_ALWAYS; break; - case GL_LESS: d3dComp = D3D11_COMPARISON_LESS; break; - case GL_LEQUAL: d3dComp = D3D11_COMPARISON_LESS_EQUAL; break; - case GL_EQUAL: d3dComp = D3D11_COMPARISON_EQUAL; break; - case GL_GREATER: d3dComp = D3D11_COMPARISON_GREATER; break; - case GL_GEQUAL: d3dComp = D3D11_COMPARISON_GREATER_EQUAL; break; - case GL_NOTEQUAL: d3dComp = D3D11_COMPARISON_NOT_EQUAL; break; - default: UNREACHABLE(); - } - - return d3dComp; -} - -D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled) -{ - return depthWriteEnabled ? D3D11_DEPTH_WRITE_MASK_ALL : D3D11_DEPTH_WRITE_MASK_ZERO; -} - -UINT8 ConvertStencilMask(GLuint stencilmask) -{ - return static_cast(stencilmask); -} - -D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp) -{ - D3D11_STENCIL_OP d3dStencilOp = D3D11_STENCIL_OP_KEEP; - - switch (stencilOp) - { - case GL_ZERO: d3dStencilOp = D3D11_STENCIL_OP_ZERO; break; - case GL_KEEP: d3dStencilOp = D3D11_STENCIL_OP_KEEP; break; - case GL_REPLACE: d3dStencilOp = D3D11_STENCIL_OP_REPLACE; break; - case GL_INCR: d3dStencilOp = D3D11_STENCIL_OP_INCR_SAT; break; - case GL_DECR: d3dStencilOp = D3D11_STENCIL_OP_DECR_SAT; break; - case GL_INVERT: d3dStencilOp = D3D11_STENCIL_OP_INVERT; break; - case GL_INCR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_INCR; break; - case GL_DECR_WRAP: d3dStencilOp = D3D11_STENCIL_OP_DECR; break; - default: UNREACHABLE(); - } - - return d3dStencilOp; -} - -D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy) -{ - if (maxAnisotropy > 1.0f) - { - return D3D11_ENCODE_ANISOTROPIC_FILTER(false); - } - else - { - D3D11_FILTER_TYPE dxMin = D3D11_FILTER_TYPE_POINT; - D3D11_FILTER_TYPE dxMip = D3D11_FILTER_TYPE_POINT; - switch (minFilter) - { - case GL_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break; - case GL_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break; - case GL_NEAREST_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_POINT; break; - case GL_LINEAR_MIPMAP_NEAREST: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_POINT; break; - case GL_NEAREST_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_POINT; dxMip = D3D11_FILTER_TYPE_LINEAR; break; - case GL_LINEAR_MIPMAP_LINEAR: dxMin = D3D11_FILTER_TYPE_LINEAR; dxMip = D3D11_FILTER_TYPE_LINEAR; break; - default: UNREACHABLE(); - } - - D3D11_FILTER_TYPE dxMag = D3D11_FILTER_TYPE_POINT; - switch (magFilter) - { - case GL_NEAREST: dxMag = D3D11_FILTER_TYPE_POINT; break; - case GL_LINEAR: dxMag = D3D11_FILTER_TYPE_LINEAR; break; - default: UNREACHABLE(); - } - - return D3D11_ENCODE_BASIC_FILTER(dxMin, dxMag, dxMip, false); - } -} - -D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap) -{ - switch (wrap) - { - case GL_REPEAT: return D3D11_TEXTURE_ADDRESS_WRAP; - case GL_CLAMP_TO_EDGE: return D3D11_TEXTURE_ADDRESS_CLAMP; - case GL_MIRRORED_REPEAT: return D3D11_TEXTURE_ADDRESS_MIRROR; - default: UNREACHABLE(); - } - - return D3D11_TEXTURE_ADDRESS_WRAP; -} - -FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset) -{ - return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast(lodOffset) : -FLT_MAX; -} - -FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset) -{ - return (minFilter == GL_NEAREST || minFilter == GL_LINEAR) ? static_cast(lodOffset) : FLT_MAX; -} - -} - -namespace d3d11_gl -{ - -GLenum ConvertBackBufferFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: return GL_RGBA8_OES; - case DXGI_FORMAT_B8G8R8A8_UNORM: return GL_BGRA8_EXT; - default: - UNREACHABLE(); - } - - return GL_RGBA8_OES; -} - -GLenum ConvertDepthStencilFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_UNKNOWN: return GL_NONE; - case DXGI_FORMAT_D16_UNORM: return GL_DEPTH_COMPONENT16; - case DXGI_FORMAT_D24_UNORM_S8_UINT: return GL_DEPTH24_STENCIL8_OES; - default: - UNREACHABLE(); - } - - return GL_DEPTH24_STENCIL8_OES; -} - -GLenum ConvertRenderbufferFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_B8G8R8A8_UNORM: - return GL_BGRA8_EXT; - case DXGI_FORMAT_R8G8B8A8_UNORM: - return GL_RGBA8_OES; - case DXGI_FORMAT_D16_UNORM: - return GL_DEPTH_COMPONENT16; - case DXGI_FORMAT_D24_UNORM_S8_UINT: - return GL_DEPTH24_STENCIL8_OES; - default: - UNREACHABLE(); - } - - return GL_RGBA8_OES; -} - -GLenum ConvertTextureInternalFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_R8G8B8A8_UNORM: - return GL_RGBA8_OES; - case DXGI_FORMAT_A8_UNORM: - return GL_ALPHA8_EXT; - case DXGI_FORMAT_BC1_UNORM: - return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - case DXGI_FORMAT_BC2_UNORM: - return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE; - case DXGI_FORMAT_BC3_UNORM: - return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE; - case DXGI_FORMAT_R32G32B32A32_FLOAT: - return GL_RGBA32F_EXT; - case DXGI_FORMAT_R32G32B32_FLOAT: - return GL_RGB32F_EXT; - case DXGI_FORMAT_R16G16B16A16_FLOAT: - return GL_RGBA16F_EXT; - case DXGI_FORMAT_B8G8R8A8_UNORM: - return GL_BGRA8_EXT; - case DXGI_FORMAT_R8_UNORM: - return GL_R8_EXT; - case DXGI_FORMAT_R8G8_UNORM: - return GL_RG8_EXT; - case DXGI_FORMAT_R16_FLOAT: - return GL_R16F_EXT; - case DXGI_FORMAT_R16G16_FLOAT: - return GL_RG16F_EXT; - case DXGI_FORMAT_D16_UNORM: - return GL_DEPTH_COMPONENT16; - case DXGI_FORMAT_D24_UNORM_S8_UINT: - return GL_DEPTH24_STENCIL8_OES; - case DXGI_FORMAT_UNKNOWN: - return GL_NONE; - default: - UNREACHABLE(); - } - - return GL_RGBA8_OES; -} - -} - -namespace gl_d3d11 -{ - -DXGI_FORMAT ConvertRenderbufferFormat(GLenum format) -{ - switch (format) - { - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGBA8_OES: - case GL_RGB565: - case GL_RGB8_OES: - return DXGI_FORMAT_R8G8B8A8_UNORM; - case GL_BGRA8_EXT: - return DXGI_FORMAT_B8G8R8A8_UNORM; - case GL_DEPTH_COMPONENT16: - return DXGI_FORMAT_D16_UNORM; - case GL_STENCIL_INDEX8: - case GL_DEPTH24_STENCIL8_OES: - return DXGI_FORMAT_D24_UNORM_S8_UINT; - default: - UNREACHABLE(); - } - - return DXGI_FORMAT_R8G8B8A8_UNORM; -} - -DXGI_FORMAT ConvertTextureFormat(GLenum internalformat, D3D_FEATURE_LEVEL featureLevel) -{ - switch (internalformat) - { - case GL_RGB565: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGB8_OES: - case GL_RGBA8_OES: - case GL_LUMINANCE8_EXT: - case GL_LUMINANCE8_ALPHA8_EXT: - return DXGI_FORMAT_R8G8B8A8_UNORM; - case GL_ALPHA8_EXT: - return featureLevel >= D3D_FEATURE_LEVEL_10_0 ? DXGI_FORMAT_A8_UNORM : DXGI_FORMAT_B8G8R8A8_UNORM; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - return DXGI_FORMAT_BC1_UNORM; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - return DXGI_FORMAT_BC2_UNORM; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - return DXGI_FORMAT_BC3_UNORM; - case GL_RGBA32F_EXT: - case GL_ALPHA32F_EXT: - case GL_LUMINANCE_ALPHA32F_EXT: - return DXGI_FORMAT_R32G32B32A32_FLOAT; - case GL_RGB32F_EXT: - case GL_LUMINANCE32F_EXT: - return DXGI_FORMAT_R32G32B32A32_FLOAT; - case GL_RGBA16F_EXT: - case GL_ALPHA16F_EXT: - case GL_LUMINANCE_ALPHA16F_EXT: - case GL_RGB16F_EXT: - case GL_LUMINANCE16F_EXT: - return DXGI_FORMAT_R16G16B16A16_FLOAT; - case GL_BGRA8_EXT: - return DXGI_FORMAT_B8G8R8A8_UNORM; - case GL_R8_EXT: - return DXGI_FORMAT_R8_UNORM; - case GL_RG8_EXT: - return DXGI_FORMAT_R8G8_UNORM; - case GL_R16F_EXT: - return DXGI_FORMAT_R16_FLOAT; - case GL_RG16F_EXT: - return DXGI_FORMAT_R16G16_FLOAT; - case GL_DEPTH_COMPONENT16: - return DXGI_FORMAT_D16_UNORM; - case GL_DEPTH_COMPONENT32_OES: - case GL_DEPTH24_STENCIL8_OES: - return DXGI_FORMAT_D24_UNORM_S8_UINT; - case GL_NONE: - return DXGI_FORMAT_UNKNOWN; - default: - UNREACHABLE(); - } - - return DXGI_FORMAT_R8G8B8A8_UNORM; -} - -} - -namespace d3d11 -{ - -void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v) -{ - vertex->x = x; - vertex->y = y; - vertex->u = u; - vertex->v = v; -} - -void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z, - const gl::Color &color) -{ - vertex->x = x; - vertex->y = y; - vertex->z = z; - vertex->r = color.red; - vertex->g = color.green; - vertex->b = color.blue; - vertex->a = color.alpha; -} - -size_t ComputePixelSizeBits(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_R1_UNORM: - return 1; - - case DXGI_FORMAT_A8_UNORM: - case DXGI_FORMAT_R8_SINT: - case DXGI_FORMAT_R8_SNORM: - case DXGI_FORMAT_R8_TYPELESS: - case DXGI_FORMAT_R8_UINT: - case DXGI_FORMAT_R8_UNORM: - return 8; - - case DXGI_FORMAT_B5G5R5A1_UNORM: - case DXGI_FORMAT_B5G6R5_UNORM: - case DXGI_FORMAT_D16_UNORM: - case DXGI_FORMAT_R16_FLOAT: - case DXGI_FORMAT_R16_SINT: - case DXGI_FORMAT_R16_SNORM: - case DXGI_FORMAT_R16_TYPELESS: - case DXGI_FORMAT_R16_UINT: - case DXGI_FORMAT_R16_UNORM: - case DXGI_FORMAT_R8G8_SINT: - case DXGI_FORMAT_R8G8_SNORM: - case DXGI_FORMAT_R8G8_TYPELESS: - case DXGI_FORMAT_R8G8_UINT: - case DXGI_FORMAT_R8G8_UNORM: - return 16; - - case DXGI_FORMAT_B8G8R8X8_TYPELESS: - case DXGI_FORMAT_B8G8R8X8_UNORM: - case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB: - case DXGI_FORMAT_D24_UNORM_S8_UINT: - case DXGI_FORMAT_D32_FLOAT: - case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: - case DXGI_FORMAT_G8R8_G8B8_UNORM: - case DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM: - case DXGI_FORMAT_R10G10B10A2_TYPELESS: - case DXGI_FORMAT_R10G10B10A2_UINT: - case DXGI_FORMAT_R10G10B10A2_UNORM: - case DXGI_FORMAT_R11G11B10_FLOAT: - case DXGI_FORMAT_R16G16_FLOAT: - case DXGI_FORMAT_R16G16_SINT: - case DXGI_FORMAT_R16G16_SNORM: - case DXGI_FORMAT_R16G16_TYPELESS: - case DXGI_FORMAT_R16G16_UINT: - case DXGI_FORMAT_R16G16_UNORM: - case DXGI_FORMAT_R24_UNORM_X8_TYPELESS: - case DXGI_FORMAT_R24G8_TYPELESS: - case DXGI_FORMAT_R32_FLOAT: - case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS: - case DXGI_FORMAT_R32_SINT: - case DXGI_FORMAT_R32_TYPELESS: - case DXGI_FORMAT_R32_UINT: - case DXGI_FORMAT_R8G8_B8G8_UNORM: - case DXGI_FORMAT_R8G8B8A8_SINT: - case DXGI_FORMAT_R8G8B8A8_SNORM: - case DXGI_FORMAT_R8G8B8A8_TYPELESS: - case DXGI_FORMAT_R8G8B8A8_UINT: - case DXGI_FORMAT_R8G8B8A8_UNORM: - case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: - case DXGI_FORMAT_B8G8R8A8_TYPELESS: - case DXGI_FORMAT_B8G8R8A8_UNORM: - case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB: - case DXGI_FORMAT_R9G9B9E5_SHAREDEXP: - case DXGI_FORMAT_X24_TYPELESS_G8_UINT: - case DXGI_FORMAT_X32_TYPELESS_G8X24_UINT: - return 32; - - case DXGI_FORMAT_R16G16B16A16_FLOAT: - case DXGI_FORMAT_R16G16B16A16_SINT: - case DXGI_FORMAT_R16G16B16A16_SNORM: - case DXGI_FORMAT_R16G16B16A16_TYPELESS: - case DXGI_FORMAT_R16G16B16A16_UINT: - case DXGI_FORMAT_R16G16B16A16_UNORM: - case DXGI_FORMAT_R32G32_FLOAT: - case DXGI_FORMAT_R32G32_SINT: - case DXGI_FORMAT_R32G32_TYPELESS: - case DXGI_FORMAT_R32G32_UINT: - case DXGI_FORMAT_R32G8X24_TYPELESS: - return 64; - - case DXGI_FORMAT_R32G32B32_FLOAT: - case DXGI_FORMAT_R32G32B32_SINT: - case DXGI_FORMAT_R32G32B32_TYPELESS: - case DXGI_FORMAT_R32G32B32_UINT: - return 96; - - case DXGI_FORMAT_R32G32B32A32_FLOAT: - case DXGI_FORMAT_R32G32B32A32_SINT: - case DXGI_FORMAT_R32G32B32A32_TYPELESS: - case DXGI_FORMAT_R32G32B32A32_UINT: - return 128; - - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_SNORM: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - return 4; - - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - return 8; - - default: - return 0; - } -} - -size_t ComputeBlockSizeBits(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_SNORM: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - return ComputePixelSizeBits(format) * 16; - default: - UNREACHABLE(); - return 0; - } -} - -bool IsCompressed(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_SNORM: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - return true; - case DXGI_FORMAT_UNKNOWN: - UNREACHABLE(); - return false; - default: - return false; - } -} - -unsigned int GetTextureFormatDimensionAlignment(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_BC1_TYPELESS: - case DXGI_FORMAT_BC1_UNORM: - case DXGI_FORMAT_BC1_UNORM_SRGB: - case DXGI_FORMAT_BC4_SNORM: - case DXGI_FORMAT_BC4_TYPELESS: - case DXGI_FORMAT_BC4_UNORM: - case DXGI_FORMAT_BC2_TYPELESS: - case DXGI_FORMAT_BC2_UNORM: - case DXGI_FORMAT_BC2_UNORM_SRGB: - case DXGI_FORMAT_BC3_TYPELESS: - case DXGI_FORMAT_BC3_UNORM: - case DXGI_FORMAT_BC3_UNORM_SRGB: - case DXGI_FORMAT_BC5_SNORM: - case DXGI_FORMAT_BC5_TYPELESS: - case DXGI_FORMAT_BC5_UNORM: - case DXGI_FORMAT_BC6H_SF16: - case DXGI_FORMAT_BC6H_TYPELESS: - case DXGI_FORMAT_BC6H_UF16: - case DXGI_FORMAT_BC7_TYPELESS: - case DXGI_FORMAT_BC7_UNORM: - case DXGI_FORMAT_BC7_UNORM_SRGB: - return 4; - case DXGI_FORMAT_UNKNOWN: - UNREACHABLE(); - return 1; - default: - return 1; - } -} - -bool IsDepthStencilFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: - case DXGI_FORMAT_D32_FLOAT: - case DXGI_FORMAT_D24_UNORM_S8_UINT: - case DXGI_FORMAT_D16_UNORM: - return true; - default: - return false; - } -} - -DXGI_FORMAT GetDepthTextureFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_R32G8X24_TYPELESS; - case DXGI_FORMAT_D32_FLOAT: return DXGI_FORMAT_R32_TYPELESS; - case DXGI_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_R24G8_TYPELESS; - case DXGI_FORMAT_D16_UNORM: return DXGI_FORMAT_R16_TYPELESS; - default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; - } -} - -DXGI_FORMAT GetDepthShaderResourceFormat(DXGI_FORMAT format) -{ - switch (format) - { - case DXGI_FORMAT_D32_FLOAT_S8X24_UINT: return DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS; - case DXGI_FORMAT_D32_FLOAT: return DXGI_FORMAT_R32_UINT; - case DXGI_FORMAT_D24_UNORM_S8_UINT: return DXGI_FORMAT_R24_UNORM_X8_TYPELESS; - case DXGI_FORMAT_D16_UNORM: return DXGI_FORMAT_R16_UNORM; - default: UNREACHABLE(); return DXGI_FORMAT_UNKNOWN; - } -} - -HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name) -{ -#if defined(_DEBUG) - return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name); -#else - return S_OK; -#endif -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h deleted file mode 100644 index 70ad4fea2b..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/renderer11_utils.h +++ /dev/null @@ -1,95 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// renderer11_utils.h: Conversion functions and other utility routines -// specific to the D3D11 renderer. - -#ifndef LIBGLESV2_RENDERER_RENDERER11_UTILS_H -#define LIBGLESV2_RENDERER_RENDERER11_UTILS_H - -#include "libGLESv2/angletypes.h" - -namespace gl_d3d11 -{ - -D3D11_BLEND ConvertBlendFunc(GLenum glBlend, bool isAlpha); -D3D11_BLEND_OP ConvertBlendOp(GLenum glBlendOp); -UINT8 ConvertColorMask(bool maskRed, bool maskGreen, bool maskBlue, bool maskAlpha); - -D3D11_CULL_MODE ConvertCullMode(bool cullEnabled, GLenum cullMode); - -D3D11_COMPARISON_FUNC ConvertComparison(GLenum comparison); -D3D11_DEPTH_WRITE_MASK ConvertDepthMask(bool depthWriteEnabled); -UINT8 ConvertStencilMask(GLuint stencilmask); -D3D11_STENCIL_OP ConvertStencilOp(GLenum stencilOp); - -D3D11_FILTER ConvertFilter(GLenum minFilter, GLenum magFilter, float maxAnisotropy); -D3D11_TEXTURE_ADDRESS_MODE ConvertTextureWrap(GLenum wrap); -FLOAT ConvertMinLOD(GLenum minFilter, unsigned int lodOffset); -FLOAT ConvertMaxLOD(GLenum minFilter, unsigned int lodOffset); - -DXGI_FORMAT ConvertRenderbufferFormat(GLenum format); -DXGI_FORMAT ConvertTextureFormat(GLenum format, D3D_FEATURE_LEVEL featureLevel); -} - -namespace d3d11_gl -{ - -GLenum ConvertBackBufferFormat(DXGI_FORMAT format); -GLenum ConvertDepthStencilFormat(DXGI_FORMAT format); -GLenum ConvertRenderbufferFormat(DXGI_FORMAT format); -GLenum ConvertTextureInternalFormat(DXGI_FORMAT format); - -} - -namespace d3d11 -{ - -struct PositionTexCoordVertex -{ - float x, y; - float u, v; -}; -void SetPositionTexCoordVertex(PositionTexCoordVertex* vertex, float x, float y, float u, float v); - -struct PositionDepthColorVertex -{ - float x, y, z; - float r, g, b, a; -}; -void SetPositionDepthColorVertex(PositionDepthColorVertex* vertex, float x, float y, float z, - const gl::Color &color); - -size_t ComputePixelSizeBits(DXGI_FORMAT format); -size_t ComputeBlockSizeBits(DXGI_FORMAT format); - -bool IsCompressed(DXGI_FORMAT format); -unsigned int GetTextureFormatDimensionAlignment(DXGI_FORMAT format); - -bool IsDepthStencilFormat(DXGI_FORMAT format); -DXGI_FORMAT GetDepthTextureFormat(DXGI_FORMAT format); -DXGI_FORMAT GetDepthShaderResourceFormat(DXGI_FORMAT format); - -HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name); - -inline bool isDeviceLostError(HRESULT errorCode) -{ - switch (errorCode) - { - case DXGI_ERROR_DEVICE_HUNG: - case DXGI_ERROR_DEVICE_REMOVED: - case DXGI_ERROR_DEVICE_RESET: - case DXGI_ERROR_DRIVER_INTERNAL_ERROR: - case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE: - return true; - default: - return false; - } -} - -} - -#endif // LIBGLESV2_RENDERER_RENDERER11_UTILS_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl deleted file mode 100644 index cb132dc99c..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Clear11.hlsl +++ /dev/null @@ -1,42 +0,0 @@ -void VS_Clear( in float3 inPosition : POSITION, in float4 inColor : COLOR, - out float4 outPosition : SV_POSITION, out float4 outColor : COLOR) -{ - outPosition = float4(inPosition, 1.0f); - outColor = inColor; -} - -// Assume we are in SM4+, which has 8 color outputs -struct PS_OutputMultiple -{ - float4 color0 : SV_TARGET0; - float4 color1 : SV_TARGET1; - float4 color2 : SV_TARGET2; - float4 color3 : SV_TARGET3; -#ifdef SM4 - float4 color4 : SV_TARGET4; - float4 color5 : SV_TARGET5; - float4 color6 : SV_TARGET6; - float4 color7 : SV_TARGET7; -#endif -}; - -PS_OutputMultiple PS_ClearMultiple(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR) -{ - PS_OutputMultiple outColor; - outColor.color0 = inColor; - outColor.color1 = inColor; - outColor.color2 = inColor; - outColor.color3 = inColor; -#ifdef SM4 - outColor.color4 = inColor; - outColor.color5 = inColor; - outColor.color6 = inColor; - outColor.color7 = inColor; -#endif - return outColor; -} - -float4 PS_ClearSingle(in float4 inPosition : SV_Position, in float4 inColor : COLOR) : SV_Target0 -{ - return inColor; -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl deleted file mode 100644 index 43b7801efc..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/shaders/Passthrough11.hlsl +++ /dev/null @@ -1,29 +0,0 @@ -Texture2D Texture : register(t0); -SamplerState Sampler : register(s0); - -void VS_Passthrough( in float2 inPosition : POSITION, in float2 inTexCoord : TEXCOORD0, - out float4 outPosition : SV_POSITION, out float2 outTexCoord : TEXCOORD0) -{ - outPosition = float4(inPosition, 0.0f, 1.0f); - outTexCoord = inTexCoord; -} - -float4 PS_PassthroughRGBA(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return Texture.Sample(Sampler, inTexCoord).rgba; -} - -float4 PS_PassthroughRGB(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return float4(Texture.Sample(Sampler, inTexCoord).rgb, 1.0f); -} - -float4 PS_PassthroughLum(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return float4(Texture.Sample(Sampler, inTexCoord).rrr, 1.0f); -} - -float4 PS_PassthroughLumAlpha(in float4 inPosition : SV_POSITION, in float2 inTexCoord : TEXCOORD0) : SV_TARGET0 -{ - return Texture.Sample(Sampler, inTexCoord).rrra; -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.cpp deleted file mode 100644 index d73df6418d..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.cpp +++ /dev/null @@ -1,595 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Blit.cpp: Surface copy utility class. - -#include "libGLESv2/renderer/d3d9/Blit.h" - -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" - -namespace -{ -#include "libGLESv2/renderer/d3d9/shaders/compiled/standardvs.h" -#include "libGLESv2/renderer/d3d9/shaders/compiled/flipyvs.h" -#include "libGLESv2/renderer/d3d9/shaders/compiled/passthroughps.h" -#include "libGLESv2/renderer/d3d9/shaders/compiled/luminanceps.h" -#include "libGLESv2/renderer/d3d9/shaders/compiled/componentmaskps.h" - -const BYTE* const g_shaderCode[] = -{ - g_vs20_standardvs, - g_vs20_flipyvs, - g_ps20_passthroughps, - g_ps20_luminanceps, - g_ps20_componentmaskps -}; - -const size_t g_shaderSize[] = -{ - sizeof(g_vs20_standardvs), - sizeof(g_vs20_flipyvs), - sizeof(g_ps20_passthroughps), - sizeof(g_ps20_luminanceps), - sizeof(g_ps20_componentmaskps) -}; -} - -namespace rx -{ -Blit::Blit(rx::Renderer9 *renderer) - : mRenderer(renderer), mQuadVertexBuffer(NULL), mQuadVertexDeclaration(NULL), mSavedStateBlock(NULL), mSavedRenderTarget(NULL), mSavedDepthStencil(NULL) -{ - initGeometry(); - memset(mCompiledShaders, 0, sizeof(mCompiledShaders)); -} - -Blit::~Blit() -{ - if (mSavedStateBlock) mSavedStateBlock->Release(); - if (mQuadVertexBuffer) mQuadVertexBuffer->Release(); - if (mQuadVertexDeclaration) mQuadVertexDeclaration->Release(); - - for (int i = 0; i < SHADER_COUNT; i++) - { - if (mCompiledShaders[i]) - { - mCompiledShaders[i]->Release(); - } - } -} - -void Blit::initGeometry() -{ - static const float quad[] = - { - -1, -1, - -1, 1, - 1, -1, - 1, 1 - }; - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - HRESULT result = device->CreateVertexBuffer(sizeof(quad), D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &mQuadVertexBuffer, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::error(GL_OUT_OF_MEMORY); - } - - void *lockPtr = NULL; - result = mQuadVertexBuffer->Lock(0, 0, &lockPtr, 0); - - if (FAILED(result) || lockPtr == NULL) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::error(GL_OUT_OF_MEMORY); - } - - memcpy(lockPtr, quad, sizeof(quad)); - mQuadVertexBuffer->Unlock(); - - static const D3DVERTEXELEMENT9 elements[] = - { - { 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, - D3DDECL_END() - }; - - result = device->CreateVertexDeclaration(elements, &mQuadVertexDeclaration); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::error(GL_OUT_OF_MEMORY); - } -} - -template -bool Blit::setShader(ShaderId source, const char *profile, - D3DShaderType *(rx::Renderer9::*createShader)(const DWORD *, size_t length), - HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)) -{ - IDirect3DDevice9 *device = mRenderer->getDevice(); - - D3DShaderType *shader; - - if (mCompiledShaders[source] != NULL) - { - shader = static_cast(mCompiledShaders[source]); - } - else - { - const BYTE* shaderCode = g_shaderCode[source]; - size_t shaderSize = g_shaderSize[source]; - - shader = (mRenderer->*createShader)(reinterpret_cast(shaderCode), shaderSize); - if (!shader) - { - ERR("Failed to create shader for blit operation"); - return false; - } - - mCompiledShaders[source] = shader; - } - - HRESULT hr = (device->*setShader)(shader); - - if (FAILED(hr)) - { - ERR("Failed to set shader for blit operation"); - return false; - } - - return true; -} - -bool Blit::setVertexShader(ShaderId shader) -{ - return setShader(shader, "vs_2_0", &rx::Renderer9::createVertexShader, &IDirect3DDevice9::SetVertexShader); -} - -bool Blit::setPixelShader(ShaderId shader) -{ - return setShader(shader, "ps_2_0", &rx::Renderer9::createPixelShader, &IDirect3DDevice9::SetPixelShader); -} - -RECT Blit::getSurfaceRect(IDirect3DSurface9 *surface) const -{ - D3DSURFACE_DESC desc; - surface->GetDesc(&desc); - - RECT rect; - rect.left = 0; - rect.top = 0; - rect.right = desc.Width; - rect.bottom = desc.Height; - - return rect; -} - -bool Blit::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) -{ - IDirect3DTexture9 *texture = copySurfaceToTexture(source, getSurfaceRect(source)); - if (!texture) - { - return false; - } - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - saveState(); - - device->SetTexture(0, texture); - device->SetRenderTarget(0, dest); - - setVertexShader(SHADER_VS_STANDARD); - setPixelShader(SHADER_PS_PASSTHROUGH); - - setCommonBlitState(); - device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); - device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); - - setViewport(getSurfaceRect(dest), 0, 0); - - render(); - - texture->Release(); - - restoreState(); - - return true; -} - -bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) -{ - RenderTarget9 *renderTarget = NULL; - IDirect3DSurface9 *source = NULL; - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); - - if (colorbuffer) - { - renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); - } - - if (renderTarget) - { - source = renderTarget->getSurface(); - } - - if (!source) - { - ERR("Failed to retrieve the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); - IDirect3DSurface9 *destSurface = storage9->getSurfaceLevel(level, true); - bool result = false; - - if (destSurface) - { - result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); - destSurface->Release(); - } - - source->Release(); - return result; -} - -bool Blit::copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) -{ - RenderTarget9 *renderTarget = NULL; - IDirect3DSurface9 *source = NULL; - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); - - if (colorbuffer) - { - renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); - } - - if (renderTarget) - { - source = renderTarget->getSurface(); - } - - if (!source) - { - ERR("Failed to retrieve the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); - IDirect3DSurface9 *destSurface = storage9->getCubeMapSurface(target, level, true); - bool result = false; - - if (destSurface) - { - result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface); - destSurface->Release(); - } - - source->Release(); - return result; -} - -bool Blit::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) -{ - if (!dest) - { - return false; - } - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - D3DSURFACE_DESC sourceDesc; - D3DSURFACE_DESC destDesc; - source->GetDesc(&sourceDesc); - dest->GetDesc(&destDesc); - - if (sourceDesc.Format == destDesc.Format && destDesc.Usage & D3DUSAGE_RENDERTARGET && - d3d9_gl::IsFormatChannelEquivalent(destDesc.Format, destFormat)) // Can use StretchRect - { - RECT destRect = {xoffset, yoffset, xoffset + (sourceRect.right - sourceRect.left), yoffset + (sourceRect.bottom - sourceRect.top)}; - HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::error(GL_OUT_OF_MEMORY, false); - } - } - else - { - return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest); - } - return true; -} - -bool Blit::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest) -{ - IDirect3DTexture9 *texture = copySurfaceToTexture(source, sourceRect); - if (!texture) - { - return false; - } - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - saveState(); - - device->SetTexture(0, texture); - device->SetRenderTarget(0, dest); - - setViewport(sourceRect, xoffset, yoffset); - - setCommonBlitState(); - if (setFormatConvertShaders(destFormat)) - { - render(); - } - - texture->Release(); - - restoreState(); - - return true; -} - -bool Blit::setFormatConvertShaders(GLenum destFormat) -{ - bool okay = setVertexShader(SHADER_VS_STANDARD); - - switch (destFormat) - { - default: UNREACHABLE(); - case GL_RGBA: - case GL_BGRA_EXT: - case GL_RGB: - case GL_ALPHA: - okay = okay && setPixelShader(SHADER_PS_COMPONENTMASK); - break; - - case GL_LUMINANCE: - case GL_LUMINANCE_ALPHA: - okay = okay && setPixelShader(SHADER_PS_LUMINANCE); - break; - } - - if (!okay) - { - return false; - } - - enum { X = 0, Y = 1, Z = 2, W = 3 }; - - // The meaning of this constant depends on the shader that was selected. - // See the shader assembly code above for details. - float psConst0[4] = { 0, 0, 0, 0 }; - - switch (destFormat) - { - default: UNREACHABLE(); - case GL_RGBA: - case GL_BGRA_EXT: - psConst0[X] = 1; - psConst0[Z] = 1; - break; - - case GL_RGB: - psConst0[X] = 1; - psConst0[W] = 1; - break; - - case GL_ALPHA: - psConst0[Z] = 1; - break; - - case GL_LUMINANCE: - psConst0[Y] = 1; - break; - - case GL_LUMINANCE_ALPHA: - psConst0[X] = 1; - break; - } - - mRenderer->getDevice()->SetPixelShaderConstantF(0, psConst0, 1); - - return true; -} - -IDirect3DTexture9 *Blit::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect) -{ - if (!surface) - { - return NULL; - } - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - D3DSURFACE_DESC sourceDesc; - surface->GetDesc(&sourceDesc); - - // Copy the render target into a texture - IDirect3DTexture9 *texture; - HRESULT result = device->CreateTexture(sourceRect.right - sourceRect.left, sourceRect.bottom - sourceRect.top, 1, D3DUSAGE_RENDERTARGET, sourceDesc.Format, D3DPOOL_DEFAULT, &texture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); - } - - IDirect3DSurface9 *textureSurface; - result = texture->GetSurfaceLevel(0, &textureSurface); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - texture->Release(); - return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); - } - - mRenderer->endScene(); - result = device->StretchRect(surface, &sourceRect, textureSurface, NULL, D3DTEXF_NONE); - - textureSurface->Release(); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - texture->Release(); - return gl::error(GL_OUT_OF_MEMORY, (IDirect3DTexture9*)NULL); - } - - return texture; -} - -void Blit::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset) -{ - IDirect3DDevice9 *device = mRenderer->getDevice(); - - D3DVIEWPORT9 vp; - vp.X = xoffset; - vp.Y = yoffset; - vp.Width = sourceRect.right - sourceRect.left; - vp.Height = sourceRect.bottom - sourceRect.top; - vp.MinZ = 0.0f; - vp.MaxZ = 1.0f; - device->SetViewport(&vp); - - float halfPixelAdjust[4] = { -1.0f/vp.Width, 1.0f/vp.Height, 0, 0 }; - device->SetVertexShaderConstantF(0, halfPixelAdjust, 1); -} - -void Blit::setCommonBlitState() -{ - IDirect3DDevice9 *device = mRenderer->getDevice(); - - device->SetDepthStencilSurface(NULL); - - device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); - device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); - device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - - device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_SRGBTEXTURE, FALSE); - device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - - RECT scissorRect = {0}; // Scissoring is disabled for flipping, but we need this to capture and restore the old rectangle - device->SetScissorRect(&scissorRect); - - for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - device->SetStreamSourceFreq(i, 1); - } -} - -void Blit::render() -{ - IDirect3DDevice9 *device = mRenderer->getDevice(); - - HRESULT hr = device->SetStreamSource(0, mQuadVertexBuffer, 0, 2 * sizeof(float)); - hr = device->SetVertexDeclaration(mQuadVertexDeclaration); - - mRenderer->startScene(); - hr = device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); -} - -void Blit::saveState() -{ - IDirect3DDevice9 *device = mRenderer->getDevice(); - - HRESULT hr; - - device->GetDepthStencilSurface(&mSavedDepthStencil); - device->GetRenderTarget(0, &mSavedRenderTarget); - - if (mSavedStateBlock == NULL) - { - hr = device->BeginStateBlock(); - ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); - - setCommonBlitState(); - - static const float dummyConst[4] = { 0, 0, 0, 0 }; - - device->SetVertexShader(NULL); - device->SetVertexShaderConstantF(0, dummyConst, 1); - device->SetPixelShader(NULL); - device->SetPixelShaderConstantF(0, dummyConst, 1); - - D3DVIEWPORT9 dummyVp; - dummyVp.X = 0; - dummyVp.Y = 0; - dummyVp.Width = 1; - dummyVp.Height = 1; - dummyVp.MinZ = 0; - dummyVp.MaxZ = 1; - - device->SetViewport(&dummyVp); - - device->SetTexture(0, NULL); - - device->SetStreamSource(0, mQuadVertexBuffer, 0, 0); - - device->SetVertexDeclaration(mQuadVertexDeclaration); - - hr = device->EndStateBlock(&mSavedStateBlock); - ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); - } - - ASSERT(mSavedStateBlock != NULL); - - if (mSavedStateBlock != NULL) - { - hr = mSavedStateBlock->Capture(); - ASSERT(SUCCEEDED(hr)); - } -} - -void Blit::restoreState() -{ - IDirect3DDevice9 *device = mRenderer->getDevice(); - - device->SetDepthStencilSurface(mSavedDepthStencil); - if (mSavedDepthStencil != NULL) - { - mSavedDepthStencil->Release(); - mSavedDepthStencil = NULL; - } - - device->SetRenderTarget(0, mSavedRenderTarget); - if (mSavedRenderTarget != NULL) - { - mSavedRenderTarget->Release(); - mSavedRenderTarget = NULL; - } - - ASSERT(mSavedStateBlock != NULL); - - if (mSavedStateBlock != NULL) - { - mSavedStateBlock->Apply(); - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.h deleted file mode 100644 index 3718028e66..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Blit.h +++ /dev/null @@ -1,94 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Blit.cpp: Surface copy utility class. - -#ifndef LIBGLESV2_BLIT_H_ -#define LIBGLESV2_BLIT_H_ - -#include "common/angleutils.h" - -namespace gl -{ -class Framebuffer; -} - -namespace rx -{ -class Renderer9; -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; - -class Blit -{ - public: - explicit Blit(Renderer9 *renderer); - ~Blit(); - - // Copy from source surface to dest surface. - // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) - bool copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); - bool copy(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); - - // Copy from source surface to dest surface. - // sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left) - // source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0. - bool formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); - - // 2x2 box filter sample from source to dest. - // Requires that source is RGB(A) and dest has the same format as source. - bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); - - private: - rx::Renderer9 *mRenderer; - - IDirect3DVertexBuffer9 *mQuadVertexBuffer; - IDirect3DVertexDeclaration9 *mQuadVertexDeclaration; - - void initGeometry(); - - bool setFormatConvertShaders(GLenum destFormat); - - bool copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest); - IDirect3DTexture9 *copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect); - void setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset); - void setCommonBlitState(); - RECT getSurfaceRect(IDirect3DSurface9 *surface) const; - - // This enum is used to index mCompiledShaders and mShaderSource. - enum ShaderId - { - SHADER_VS_STANDARD, - SHADER_VS_FLIPY, - SHADER_PS_PASSTHROUGH, - SHADER_PS_LUMINANCE, - SHADER_PS_COMPONENTMASK, - SHADER_COUNT - }; - - // This actually contains IDirect3DVertexShader9 or IDirect3DPixelShader9 casted to IUnknown. - IUnknown *mCompiledShaders[SHADER_COUNT]; - - template - bool setShader(ShaderId source, const char *profile, - D3DShaderType *(Renderer9::*createShader)(const DWORD *, size_t length), - HRESULT (WINAPI IDirect3DDevice9::*setShader)(D3DShaderType*)); - - bool setVertexShader(ShaderId shader); - bool setPixelShader(ShaderId shader); - void render(); - - void saveState(); - void restoreState(); - IDirect3DStateBlock9 *mSavedStateBlock; - IDirect3DSurface9 *mSavedRenderTarget; - IDirect3DSurface9 *mSavedDepthStencil; - - DISALLOW_COPY_AND_ASSIGN(Blit); -}; -} - -#endif // LIBGLESV2_BLIT_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp deleted file mode 100644 index 9fdc1246f1..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.cpp +++ /dev/null @@ -1,78 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BufferStorage9.cpp Defines the BufferStorage9 class. - -#include "libGLESv2/renderer/d3d9/BufferStorage9.h" -#include "common/debug.h" - -namespace rx -{ - -BufferStorage9::BufferStorage9() -{ - mMemory = NULL; - mAllocatedSize = 0; - mSize = 0; -} - -BufferStorage9::~BufferStorage9() -{ - delete[] mMemory; -} - -BufferStorage9 *BufferStorage9::makeBufferStorage9(BufferStorage *bufferStorage) -{ - ASSERT(HAS_DYNAMIC_TYPE(BufferStorage9*, bufferStorage)); - return static_cast(bufferStorage); -} - -void *BufferStorage9::getData() -{ - return mMemory; -} - -void BufferStorage9::setData(const void* data, unsigned int size, unsigned int offset) -{ - if (!mMemory || offset + size > mAllocatedSize) - { - unsigned int newAllocatedSize = offset + size; - void *newMemory = new char[newAllocatedSize]; - - if (offset > 0 && mMemory && mAllocatedSize > 0) - { - memcpy(newMemory, mMemory, std::min(offset, mAllocatedSize)); - } - - delete[] mMemory; - mMemory = newMemory; - mAllocatedSize = newAllocatedSize; - } - - mSize = std::max(mSize, offset + size); - if (data) - { - memcpy(reinterpret_cast(mMemory) + offset, data, size); - } -} - -void BufferStorage9::clear() -{ - mSize = 0; -} - -unsigned int BufferStorage9::getSize() const -{ - return mSize; -} - -bool BufferStorage9::supportsDirectBinding() const -{ - return false; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h deleted file mode 100644 index 3e803969bc..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/BufferStorage9.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// BufferStorage9.h Defines the BufferStorage9 class. - -#ifndef LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_ -#define LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_ - -#include "libGLESv2/renderer/BufferStorage.h" - -namespace rx -{ - -class BufferStorage9 : public BufferStorage -{ - public: - BufferStorage9(); - virtual ~BufferStorage9(); - - static BufferStorage9 *makeBufferStorage9(BufferStorage *bufferStorage); - - virtual void *getData(); - virtual void setData(const void* data, unsigned int size, unsigned int offset); - virtual void clear(); - virtual unsigned int getSize() const; - virtual bool supportsDirectBinding() const; - - private: - DISALLOW_COPY_AND_ASSIGN(BufferStorage9); - - void *mMemory; - unsigned int mAllocatedSize; - - unsigned int mSize; -}; - -} - -#endif // LIBGLESV2_RENDERER_BUFFERSTORAGE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp deleted file mode 100644 index 639c37b4e4..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Fence9.cpp: Defines the rx::Fence9 class. - -#include "libGLESv2/renderer/d3d9/Fence9.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" - -namespace rx -{ - -Fence9::Fence9(rx::Renderer9 *renderer) -{ - mRenderer = renderer; - mQuery = NULL; -} - -Fence9::~Fence9() -{ - if (mQuery) - { - mRenderer->freeEventQuery(mQuery); - mQuery = NULL; - } -} - -GLboolean Fence9::isFence() -{ - // GL_NV_fence spec: - // A name returned by GenFencesNV, but not yet set via SetFenceNV, is not the name of an existing fence. - return mQuery != NULL; -} - -void Fence9::setFence(GLenum condition) -{ - if (!mQuery) - { - mQuery = mRenderer->allocateEventQuery(); - if (!mQuery) - { - return gl::error(GL_OUT_OF_MEMORY); - } - } - - HRESULT result = mQuery->Issue(D3DISSUE_END); - ASSERT(SUCCEEDED(result)); - - setCondition(condition); - setStatus(GL_FALSE); -} - -GLboolean Fence9::testFence() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION, GL_TRUE); - } - - HRESULT result = mQuery->GetData(NULL, 0, D3DGETDATA_FLUSH); - - if (d3d9::isDeviceLostError(result)) - { - mRenderer->notifyDeviceLost(); - return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); - } - - ASSERT(result == S_OK || result == S_FALSE); - setStatus(result == S_OK); - return getStatus(); -} - -void Fence9::finishFence() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - while (!testFence()) - { - Sleep(0); - } -} - -void Fence9::getFenceiv(GLenum pname, GLint *params) -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - switch (pname) - { - case GL_FENCE_STATUS_NV: - { - // GL_NV_fence spec: - // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV - // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence. - if (getStatus()) - { - params[0] = GL_TRUE; - return; - } - - HRESULT result = mQuery->GetData(NULL, 0, 0); - - if (d3d9::isDeviceLostError(result)) - { - params[0] = GL_TRUE; - mRenderer->notifyDeviceLost(); - return gl::error(GL_OUT_OF_MEMORY); - } - - ASSERT(result == S_OK || result == S_FALSE); - setStatus(result == S_OK); - params[0] = getStatus(); - - break; - } - case GL_FENCE_CONDITION_NV: - params[0] = getCondition(); - break; - default: - return gl::error(GL_INVALID_ENUM); - break; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.h deleted file mode 100644 index 9f17641e51..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Fence9.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Fence9.h: Defines the rx::Fence9 class which implements rx::FenceImpl. - -#ifndef LIBGLESV2_RENDERER_FENCE9_H_ -#define LIBGLESV2_RENDERER_FENCE9_H_ - -#include "libGLESv2/renderer/FenceImpl.h" - -namespace rx -{ -class Renderer9; - -class Fence9 : public FenceImpl -{ - public: - explicit Fence9(rx::Renderer9 *renderer); - virtual ~Fence9(); - - GLboolean isFence(); - void setFence(GLenum condition); - GLboolean testFence(); - void finishFence(); - void getFenceiv(GLenum pname, GLint *params); - - private: - DISALLOW_COPY_AND_ASSIGN(Fence9); - - rx::Renderer9 *mRenderer; - IDirect3DQuery9 *mQuery; -}; - -} - -#endif // LIBGLESV2_RENDERER_FENCE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp deleted file mode 100644 index cd12d8cc9e..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.cpp +++ /dev/null @@ -1,736 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Image9.cpp: Implements the rx::Image9 class, which acts as the interface to -// the actual underlying surfaces of a Texture. - -#include "libGLESv2/renderer/d3d9/Image9.h" - -#include "libGLESv2/main.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d9/TextureStorage9.h" - -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/generatemip.h" - -namespace rx -{ - -Image9::Image9() -{ - mSurface = NULL; - mRenderer = NULL; - - mD3DPool = D3DPOOL_SYSTEMMEM; - mD3DFormat = D3DFMT_UNKNOWN; -} - -Image9::~Image9() -{ - if (mSurface) - { - mSurface->Release(); - } -} - -void Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface) -{ - D3DSURFACE_DESC destDesc; - HRESULT result = destSurface->GetDesc(&destDesc); - ASSERT(SUCCEEDED(result)); - - D3DSURFACE_DESC sourceDesc; - result = sourceSurface->GetDesc(&sourceDesc); - ASSERT(SUCCEEDED(result)); - - ASSERT(sourceDesc.Format == destDesc.Format); - ASSERT(sourceDesc.Width == 1 || sourceDesc.Width / 2 == destDesc.Width); - ASSERT(sourceDesc.Height == 1 || sourceDesc.Height / 2 == destDesc.Height); - - D3DLOCKED_RECT sourceLocked = {0}; - result = sourceSurface->LockRect(&sourceLocked, NULL, D3DLOCK_READONLY); - ASSERT(SUCCEEDED(result)); - - D3DLOCKED_RECT destLocked = {0}; - result = destSurface->LockRect(&destLocked, NULL, 0); - ASSERT(SUCCEEDED(result)); - - const unsigned char *sourceData = reinterpret_cast(sourceLocked.pBits); - unsigned char *destData = reinterpret_cast(destLocked.pBits); - - if (sourceData && destData) - { - switch (sourceDesc.Format) - { - case D3DFMT_L8: - GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - case D3DFMT_A8L8: - GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: - GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - case D3DFMT_A16B16G16R16F: - GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - case D3DFMT_A32B32G32R32F: - GenerateMip(sourceDesc.Width, sourceDesc.Height, sourceData, sourceLocked.Pitch, destData, destLocked.Pitch); - break; - default: - UNREACHABLE(); - break; - } - - destSurface->UnlockRect(); - sourceSurface->UnlockRect(); - } -} - -Image9 *Image9::makeImage9(Image *img) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::Image9*, img)); - return static_cast(img); -} - -void Image9::generateMipmap(Image9 *dest, Image9 *source) -{ - IDirect3DSurface9 *sourceSurface = source->getSurface(); - if (sourceSurface == NULL) - return gl::error(GL_OUT_OF_MEMORY); - - IDirect3DSurface9 *destSurface = dest->getSurface(); - generateMip(destSurface, sourceSurface); - - dest->markDirty(); -} - -void Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source) -{ - D3DLOCKED_RECT sourceLock = {0}; - D3DLOCKED_RECT destLock = {0}; - - source->LockRect(&sourceLock, NULL, 0); - dest->LockRect(&destLock, NULL, 0); - - if (sourceLock.pBits && destLock.pBits) - { - D3DSURFACE_DESC desc; - source->GetDesc(&desc); - - int rows = d3d9::IsCompressedFormat(desc.Format) ? desc.Height / 4 : desc.Height; - int bytes = d3d9::ComputeRowSize(desc.Format, desc.Width); - ASSERT(bytes <= sourceLock.Pitch && bytes <= destLock.Pitch); - - for(int i = 0; i < rows; i++) - { - memcpy((char*)destLock.pBits + destLock.Pitch * i, (char*)sourceLock.pBits + sourceLock.Pitch * i, bytes); - } - - source->UnlockRect(); - dest->UnlockRect(); - } - else UNREACHABLE(); -} - -bool Image9::redefine(rx::Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease) -{ - if (mWidth != width || - mHeight != height || - mInternalFormat != internalformat || - forceRelease) - { - mRenderer = Renderer9::makeRenderer9(renderer); - - mWidth = width; - mHeight = height; - mInternalFormat = internalformat; - // compute the d3d format that will be used - mD3DFormat = mRenderer->ConvertTextureInternalFormat(internalformat); - mActualFormat = d3d9_gl::GetEquivalentFormat(mD3DFormat); - - if (mSurface) - { - mSurface->Release(); - mSurface = NULL; - } - - return true; - } - - return false; -} - -void Image9::createSurface() -{ - if(mSurface) - { - return; - } - - IDirect3DTexture9 *newTexture = NULL; - IDirect3DSurface9 *newSurface = NULL; - const D3DPOOL poolToUse = D3DPOOL_SYSTEMMEM; - const D3DFORMAT d3dFormat = getD3DFormat(); - ASSERT(d3dFormat != D3DFMT_INTZ); // We should never get here for depth textures - - if (mWidth != 0 && mHeight != 0) - { - int levelToFetch = 0; - GLsizei requestWidth = mWidth; - GLsizei requestHeight = mHeight; - gl::MakeValidSize(true, gl::IsCompressed(mInternalFormat), &requestWidth, &requestHeight, &levelToFetch); - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - HRESULT result = device->CreateTexture(requestWidth, requestHeight, levelToFetch + 1, 0, d3dFormat, - poolToUse, &newTexture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - ERR("Creating image surface failed."); - return gl::error(GL_OUT_OF_MEMORY); - } - - newTexture->GetSurfaceLevel(levelToFetch, &newSurface); - newTexture->Release(); - } - - mSurface = newSurface; - mDirty = false; - mD3DPool = poolToUse; -} - -HRESULT Image9::lock(D3DLOCKED_RECT *lockedRect, const RECT *rect) -{ - createSurface(); - - HRESULT result = D3DERR_INVALIDCALL; - - if (mSurface) - { - result = mSurface->LockRect(lockedRect, rect, 0); - ASSERT(SUCCEEDED(result)); - - mDirty = true; - } - - return result; -} - -void Image9::unlock() -{ - if (mSurface) - { - HRESULT result = mSurface->UnlockRect(); - ASSERT(SUCCEEDED(result)); - } -} - -bool Image9::isRenderableFormat() const -{ - return TextureStorage9::IsTextureFormatRenderable(getD3DFormat()); -} - -D3DFORMAT Image9::getD3DFormat() const -{ - // this should only happen if the image hasn't been redefined first - // which would be a bug by the caller - ASSERT(mD3DFormat != D3DFMT_UNKNOWN); - - return mD3DFormat; -} - -IDirect3DSurface9 *Image9::getSurface() -{ - createSurface(); - - return mSurface; -} - -void Image9::setManagedSurface(TextureStorageInterface2D *storage, int level) -{ - TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); - setManagedSurface(storage9->getSurfaceLevel(level, false)); -} - -void Image9::setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level) -{ - TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); - setManagedSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, false)); -} - -void Image9::setManagedSurface(IDirect3DSurface9 *surface) -{ - D3DSURFACE_DESC desc; - surface->GetDesc(&desc); - ASSERT(desc.Pool == D3DPOOL_MANAGED); - - if ((GLsizei)desc.Width == mWidth && (GLsizei)desc.Height == mHeight) - { - if (mSurface) - { - copyLockableSurfaces(surface, mSurface); - mSurface->Release(); - } - - mSurface = surface; - mD3DPool = desc.Pool; - } -} - -bool Image9::updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - ASSERT(getSurface() != NULL); - TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage->getStorageInstance()); - return updateSurface(storage9->getSurfaceLevel(level, true), xoffset, yoffset, width, height); -} - -bool Image9::updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - ASSERT(getSurface() != NULL); - TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage->getStorageInstance()); - return updateSurface(storage9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true), xoffset, yoffset, width, height); -} - -bool Image9::updateSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height) -{ - if (!destSurface) - return false; - - IDirect3DSurface9 *sourceSurface = getSurface(); - - if (sourceSurface && sourceSurface != destSurface) - { - RECT rect; - rect.left = xoffset; - rect.top = yoffset; - rect.right = xoffset + width; - rect.bottom = yoffset + height; - - POINT point = {rect.left, rect.top}; - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - if (mD3DPool == D3DPOOL_MANAGED) - { - D3DSURFACE_DESC desc; - sourceSurface->GetDesc(&desc); - - IDirect3DSurface9 *surf = 0; - HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); - - if (SUCCEEDED(result)) - { - copyLockableSurfaces(surf, sourceSurface); - result = device->UpdateSurface(surf, &rect, destSurface, &point); - ASSERT(SUCCEEDED(result)); - surf->Release(); - } - } - else - { - // UpdateSurface: source must be SYSTEMMEM, dest must be DEFAULT pools - HRESULT result = device->UpdateSurface(sourceSurface, &rect, destSurface, &point); - ASSERT(SUCCEEDED(result)); - } - } - - destSurface->Release(); - return true; -} - -// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input -// into the target pixel rectangle. -void Image9::loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input) -{ - RECT lockRect = - { - xoffset, yoffset, - xoffset + width, yoffset + height - }; - - D3DLOCKED_RECT locked; - HRESULT result = lock(&locked, &lockRect); - if (FAILED(result)) - { - return; - } - - - GLsizei inputPitch = gl::ComputePitch(width, mInternalFormat, unpackAlignment); - - switch (mInternalFormat) - { - case GL_ALPHA8_EXT: -#if defined(__SSE2__) - if (gl::supportsSSE2()) - { - loadAlphaDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - else -#endif - { - loadAlphaDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - break; - case GL_LUMINANCE8_EXT: - loadLuminanceDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_L8); - break; - case GL_ALPHA32F_EXT: - loadAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE32F_EXT: - loadLuminanceFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_ALPHA16F_EXT: - loadAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE16F_EXT: - loadLuminanceHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE8_ALPHA8_EXT: - loadLuminanceAlphaDataToNativeOrBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits, getD3DFormat() == D3DFMT_A8L8); - break; - case GL_LUMINANCE_ALPHA32F_EXT: - loadLuminanceAlphaFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_LUMINANCE_ALPHA16F_EXT: - loadLuminanceAlphaHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB8_OES: - loadRGBUByteDataToBGRX(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB565: - loadRGB565DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGBA8_OES: -#if defined(__SSE2__) - if (gl::supportsSSE2()) - { - loadRGBAUByteDataToBGRASSE2(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - else -#endif - { - loadRGBAUByteDataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - } - break; - case GL_RGBA4: - loadRGBA4444DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB5_A1: - loadRGBA5551DataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_BGRA8_EXT: - loadBGRADataToBGRA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - // float textures are converted to RGBA, not BGRA, as they're stored that way in D3D - case GL_RGB32F_EXT: - loadRGBFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGB16F_EXT: - loadRGBHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGBA32F_EXT: - loadRGBAFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - case GL_RGBA16F_EXT: - loadRGBAHalfFloatDataToRGBA(width, height, inputPitch, input, locked.Pitch, locked.pBits); - break; - default: UNREACHABLE(); - } - - unlock(); -} - -void Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - const void *input) -{ - ASSERT(xoffset % 4 == 0); - ASSERT(yoffset % 4 == 0); - - RECT lockRect = { - xoffset, yoffset, - xoffset + width, yoffset + height - }; - - D3DLOCKED_RECT locked; - HRESULT result = lock(&locked, &lockRect); - if (FAILED(result)) - { - return; - } - - GLsizei inputSize = gl::ComputeCompressedSize(width, height, mInternalFormat); - GLsizei inputPitch = gl::ComputeCompressedPitch(width, mInternalFormat); - int rows = inputSize / inputPitch; - for (int i = 0; i < rows; ++i) - { - memcpy((void*)((BYTE*)locked.pBits + i * locked.Pitch), (void*)((BYTE*)input + i * inputPitch), inputPitch); - } - - unlock(); -} - -// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures -void Image9::copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) -{ - RenderTarget9 *renderTarget = NULL; - IDirect3DSurface9 *surface = NULL; - gl::Renderbuffer *colorbuffer = source->getColorbuffer(0); - - if (colorbuffer) - { - renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); - } - - if (renderTarget) - { - surface = renderTarget->getSurface(); - } - - if (!surface) - { - ERR("Failed to retrieve the render target."); - return gl::error(GL_OUT_OF_MEMORY); - } - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - IDirect3DSurface9 *renderTargetData = NULL; - D3DSURFACE_DESC description; - surface->GetDesc(&description); - - HRESULT result = device->CreateOffscreenPlainSurface(description.Width, description.Height, description.Format, D3DPOOL_SYSTEMMEM, &renderTargetData, NULL); - - if (FAILED(result)) - { - ERR("Could not create matching destination surface."); - surface->Release(); - return gl::error(GL_OUT_OF_MEMORY); - } - - result = device->GetRenderTargetData(surface, renderTargetData); - - if (FAILED(result)) - { - ERR("GetRenderTargetData unexpectedly failed."); - renderTargetData->Release(); - surface->Release(); - return gl::error(GL_OUT_OF_MEMORY); - } - - RECT sourceRect = {x, y, x + width, y + height}; - RECT destRect = {xoffset, yoffset, xoffset + width, yoffset + height}; - - D3DLOCKED_RECT sourceLock = {0}; - result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0); - - if (FAILED(result)) - { - ERR("Failed to lock the source surface (rectangle might be invalid)."); - renderTargetData->Release(); - surface->Release(); - return gl::error(GL_OUT_OF_MEMORY); - } - - D3DLOCKED_RECT destLock = {0}; - result = lock(&destLock, &destRect); - - if (FAILED(result)) - { - ERR("Failed to lock the destination surface (rectangle might be invalid)."); - renderTargetData->UnlockRect(); - renderTargetData->Release(); - surface->Release(); - return gl::error(GL_OUT_OF_MEMORY); - } - - if (destLock.pBits && sourceLock.pBits) - { - unsigned char *source = (unsigned char*)sourceLock.pBits; - unsigned char *dest = (unsigned char*)destLock.pBits; - - switch (description.Format) - { - case D3DFMT_X8R8G8B8: - case D3DFMT_A8R8G8B8: - switch(getD3DFormat()) - { - case D3DFMT_X8R8G8B8: - case D3DFMT_A8R8G8B8: - for(int y = 0; y < height; y++) - { - memcpy(dest, source, 4 * width); - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - dest[x] = source[x * 4 + 2]; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_A8L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - dest[x * 2 + 0] = source[x * 4 + 2]; - dest[x * 2 + 1] = source[x * 4 + 3]; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - default: - UNREACHABLE(); - } - break; - case D3DFMT_R5G6B5: - switch(getD3DFormat()) - { - case D3DFMT_X8R8G8B8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned short rgb = ((unsigned short*)source)[x]; - unsigned char red = (rgb & 0xF800) >> 8; - unsigned char green = (rgb & 0x07E0) >> 3; - unsigned char blue = (rgb & 0x001F) << 3; - dest[x + 0] = blue | (blue >> 5); - dest[x + 1] = green | (green >> 6); - dest[x + 2] = red | (red >> 5); - dest[x + 3] = 0xFF; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned char red = source[x * 2 + 1] & 0xF8; - dest[x] = red | (red >> 5); - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - default: - UNREACHABLE(); - } - break; - case D3DFMT_A1R5G5B5: - switch(getD3DFormat()) - { - case D3DFMT_X8R8G8B8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned short argb = ((unsigned short*)source)[x]; - unsigned char red = (argb & 0x7C00) >> 7; - unsigned char green = (argb & 0x03E0) >> 2; - unsigned char blue = (argb & 0x001F) << 3; - dest[x + 0] = blue | (blue >> 5); - dest[x + 1] = green | (green >> 5); - dest[x + 2] = red | (red >> 5); - dest[x + 3] = 0xFF; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_A8R8G8B8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned short argb = ((unsigned short*)source)[x]; - unsigned char red = (argb & 0x7C00) >> 7; - unsigned char green = (argb & 0x03E0) >> 2; - unsigned char blue = (argb & 0x001F) << 3; - unsigned char alpha = (signed short)argb >> 15; - dest[x + 0] = blue | (blue >> 5); - dest[x + 1] = green | (green >> 5); - dest[x + 2] = red | (red >> 5); - dest[x + 3] = alpha; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned char red = source[x * 2 + 1] & 0x7C; - dest[x] = (red << 1) | (red >> 4); - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - case D3DFMT_A8L8: - for(int y = 0; y < height; y++) - { - for(int x = 0; x < width; x++) - { - unsigned char red = source[x * 2 + 1] & 0x7C; - dest[x * 2 + 0] = (red << 1) | (red >> 4); - dest[x * 2 + 1] = (signed char)source[x * 2 + 1] >> 7; - } - - source += sourceLock.Pitch; - dest += destLock.Pitch; - } - break; - default: - UNREACHABLE(); - } - break; - default: - UNREACHABLE(); - } - } - - unlock(); - renderTargetData->UnlockRect(); - - renderTargetData->Release(); - surface->Release(); - - mDirty = true; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.h deleted file mode 100644 index 2fbbca3124..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Image9.h +++ /dev/null @@ -1,79 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Image9.h: Defines the rx::Image9 class, which acts as the interface to -// the actual underlying surfaces of a Texture. - -#ifndef LIBGLESV2_RENDERER_IMAGE9_H_ -#define LIBGLESV2_RENDERER_IMAGE9_H_ - -#include "libGLESv2/renderer/Image.h" -#include "common/debug.h" - -namespace gl -{ -class Framebuffer; -} - -namespace rx -{ -class Renderer; -class Renderer9; -class TextureStorageInterface2D; -class TextureStorageInterfaceCube; - -class Image9 : public Image -{ - public: - Image9(); - ~Image9(); - - static Image9 *makeImage9(Image *img); - - static void generateMipmap(Image9 *dest, Image9 *source); - static void generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface); - static void copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source); - - virtual bool redefine(Renderer *renderer, GLint internalformat, GLsizei width, GLsizei height, bool forceRelease); - - virtual bool isRenderableFormat() const; - D3DFORMAT getD3DFormat() const; - - virtual bool isDirty() const {return mSurface && mDirty;} - IDirect3DSurface9 *getSurface(); - - virtual void setManagedSurface(TextureStorageInterface2D *storage, int level); - virtual void setManagedSurface(TextureStorageInterfaceCube *storage, int face, int level); - virtual bool updateSurface(TextureStorageInterface2D *storage, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - virtual bool updateSurface(TextureStorageInterfaceCube *storage, int face, int level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - - virtual void loadData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - GLint unpackAlignment, const void *input); - virtual void loadCompressedData(GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, - const void *input); - - virtual void copy(GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source); - - private: - DISALLOW_COPY_AND_ASSIGN(Image9); - - void createSurface(); - void setManagedSurface(IDirect3DSurface9 *surface); - bool updateSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height); - - HRESULT lock(D3DLOCKED_RECT *lockedRect, const RECT *rect); - void unlock(); - - Renderer9 *mRenderer; - - D3DPOOL mD3DPool; // can only be D3DPOOL_SYSTEMMEM or D3DPOOL_MANAGED since it needs to be lockable. - D3DFORMAT mD3DFormat; - - IDirect3DSurface9 *mSurface; -}; -} - -#endif // LIBGLESV2_RENDERER_IMAGE9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp deleted file mode 100644 index 7cb5d13a18..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.cpp +++ /dev/null @@ -1,207 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation. - -#include "libGLESv2/renderer/d3d9/IndexBuffer9.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" - -namespace rx -{ - -IndexBuffer9::IndexBuffer9(Renderer9 *const renderer) : mRenderer(renderer) -{ - mIndexBuffer = NULL; - mBufferSize = 0; - mIndexType = 0; - mDynamic = false; -} - -IndexBuffer9::~IndexBuffer9() -{ - if (mIndexBuffer) - { - mIndexBuffer->Release(); - mIndexBuffer = NULL; - } -} - -bool IndexBuffer9::initialize(unsigned int bufferSize, GLenum indexType, bool dynamic) -{ - if (mIndexBuffer) - { - mIndexBuffer->Release(); - mIndexBuffer = NULL; - } - - updateSerial(); - - if (bufferSize > 0) - { - D3DFORMAT format; - if (indexType == GL_UNSIGNED_SHORT || indexType == GL_UNSIGNED_BYTE) - { - format = D3DFMT_INDEX16; - } - else if (indexType == GL_UNSIGNED_INT) - { - if (mRenderer->get32BitIndexSupport()) - { - format = D3DFMT_INDEX32; - } - else - { - ERR("Attempted to create a 32-bit index buffer but renderer does not support 32-bit indices."); - return false; - } - } - else - { - ERR("Invalid index type %u.", indexType); - return false; - } - - DWORD usageFlags = D3DUSAGE_WRITEONLY; - if (dynamic) - { - usageFlags |= D3DUSAGE_DYNAMIC; - } - - HRESULT result = mRenderer->createIndexBuffer(bufferSize, usageFlags, format, &mIndexBuffer); - if (FAILED(result)) - { - ERR("Failed to create an index buffer of size %u, result: 0x%08x.", mBufferSize, result); - return false; - } - } - - mBufferSize = bufferSize; - mIndexType = indexType; - mDynamic = dynamic; - - return true; -} - -IndexBuffer9 *IndexBuffer9::makeIndexBuffer9(IndexBuffer *indexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(IndexBuffer9*, indexBuffer)); - return static_cast(indexBuffer); -} - -bool IndexBuffer9::mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory) -{ - if (mIndexBuffer) - { - DWORD lockFlags = mDynamic ? D3DLOCK_NOOVERWRITE : 0; - - void *mapPtr = NULL; - HRESULT result = mIndexBuffer->Lock(offset, size, &mapPtr, lockFlags); - if (FAILED(result)) - { - ERR("Index buffer lock failed with error 0x%08x", result); - return false; - } - - *outMappedMemory = mapPtr; - return true; - } - else - { - ERR("Index buffer not initialized."); - return false; - } -} - -bool IndexBuffer9::unmapBuffer() -{ - if (mIndexBuffer) - { - HRESULT result = mIndexBuffer->Unlock(); - if (FAILED(result)) - { - ERR("Index buffer unlock failed with error 0x%08x", result); - return false; - } - - return true; - } - else - { - ERR("Index buffer not initialized."); - return false; - } -} - -GLenum IndexBuffer9::getIndexType() const -{ - return mIndexType; -} - -unsigned int IndexBuffer9::getBufferSize() const -{ - return mBufferSize; -} - -bool IndexBuffer9::setSize(unsigned int bufferSize, GLenum indexType) -{ - if (bufferSize > mBufferSize || indexType != mIndexType) - { - return initialize(bufferSize, indexType, mDynamic); - } - else - { - return true; - } -} - -bool IndexBuffer9::discard() -{ - if (mIndexBuffer) - { - void *dummy; - HRESULT result; - - result = mIndexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); - if (FAILED(result)) - { - ERR("Discard lock failed with error 0x%08x", result); - return false; - } - - result = mIndexBuffer->Unlock(); - if (FAILED(result)) - { - ERR("Discard unlock failed with error 0x%08x", result); - return false; - } - - return true; - } - else - { - ERR("Index buffer not initialized."); - return false; - } -} - -D3DFORMAT IndexBuffer9::getIndexFormat() const -{ - switch (mIndexType) - { - case GL_UNSIGNED_BYTE: return D3DFMT_INDEX16; - case GL_UNSIGNED_SHORT: return D3DFMT_INDEX16; - case GL_UNSIGNED_INT: return D3DFMT_INDEX32; - default: UNREACHABLE(); return D3DFMT_UNKNOWN; - } -} - -IDirect3DIndexBuffer9 * IndexBuffer9::getBuffer() const -{ - return mIndexBuffer; -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h deleted file mode 100644 index 6801867532..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/IndexBuffer9.h +++ /dev/null @@ -1,53 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Indexffer9.h: Defines the D3D9 IndexBuffer implementation. - -#ifndef LIBGLESV2_RENDERER_INDEXBUFFER9_H_ -#define LIBGLESV2_RENDERER_INDEXBUFFER9_H_ - -#include "libGLESv2/renderer/IndexBuffer.h" - -namespace rx -{ -class Renderer9; - -class IndexBuffer9 : public IndexBuffer -{ - public: - explicit IndexBuffer9(Renderer9 *const renderer); - virtual ~IndexBuffer9(); - - virtual bool initialize(unsigned int bufferSize, GLenum indexType, bool dynamic); - - static IndexBuffer9 *makeIndexBuffer9(IndexBuffer *indexBuffer); - - virtual bool mapBuffer(unsigned int offset, unsigned int size, void** outMappedMemory); - virtual bool unmapBuffer(); - - virtual GLenum getIndexType() const; - virtual unsigned int getBufferSize() const; - virtual bool setSize(unsigned int bufferSize, GLenum indexType); - - virtual bool discard(); - - D3DFORMAT getIndexFormat() const; - IDirect3DIndexBuffer9 *getBuffer() const; - - private: - DISALLOW_COPY_AND_ASSIGN(IndexBuffer9); - - rx::Renderer9 *const mRenderer; - - IDirect3DIndexBuffer9 *mIndexBuffer; - unsigned int mBufferSize; - GLenum mIndexType; - bool mDynamic; -}; - -} - -#endif // LIBGLESV2_RENDERER_INDEXBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp deleted file mode 100644 index 72781cbc39..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.cpp +++ /dev/null @@ -1,125 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl. - - -#include "libGLESv2/renderer/d3d9/Query9.h" -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" - -namespace rx -{ - -Query9::Query9(rx::Renderer9 *renderer, GLenum type) : QueryImpl(type) -{ - mRenderer = renderer; - mQuery = NULL; -} - -Query9::~Query9() -{ - if (mQuery) - { - mQuery->Release(); - mQuery = NULL; - } -} - -void Query9::begin() -{ - if (mQuery == NULL) - { - if (FAILED(mRenderer->getDevice()->CreateQuery(D3DQUERYTYPE_OCCLUSION, &mQuery))) - { - return gl::error(GL_OUT_OF_MEMORY); - } - } - - HRESULT result = mQuery->Issue(D3DISSUE_BEGIN); - ASSERT(SUCCEEDED(result)); -} - -void Query9::end() -{ - if (mQuery == NULL) - { - return gl::error(GL_INVALID_OPERATION); - } - - HRESULT result = mQuery->Issue(D3DISSUE_END); - ASSERT(SUCCEEDED(result)); - - mStatus = GL_FALSE; - mResult = GL_FALSE; -} - -GLuint Query9::getResult() -{ - if (mQuery != NULL) - { - while (!testQuery()) - { - Sleep(0); - // explicitly check for device loss - // some drivers seem to return S_FALSE even if the device is lost - // instead of D3DERR_DEVICELOST like they should - if (mRenderer->testDeviceLost(true)) - { - return gl::error(GL_OUT_OF_MEMORY, 0); - } - } - } - - return mResult; -} - -GLboolean Query9::isResultAvailable() -{ - if (mQuery != NULL) - { - testQuery(); - } - - return mStatus; -} - -GLboolean Query9::testQuery() -{ - if (mQuery != NULL && mStatus != GL_TRUE) - { - DWORD numPixels = 0; - - HRESULT hres = mQuery->GetData(&numPixels, sizeof(DWORD), D3DGETDATA_FLUSH); - if (hres == S_OK) - { - mStatus = GL_TRUE; - - switch (getType()) - { - case GL_ANY_SAMPLES_PASSED_EXT: - case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT: - mResult = (numPixels > 0) ? GL_TRUE : GL_FALSE; - break; - default: - ASSERT(false); - } - } - else if (d3d9::isDeviceLostError(hres)) - { - mRenderer->notifyDeviceLost(); - return gl::error(GL_OUT_OF_MEMORY, GL_TRUE); - } - - return mStatus; - } - - return GL_TRUE; // prevent blocking when query is null -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.h deleted file mode 100644 index 47eef89336..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Query9.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Query9.h: Defines the rx::Query9 class which implements rx::QueryImpl. - -#ifndef LIBGLESV2_RENDERER_QUERY9_H_ -#define LIBGLESV2_RENDERER_QUERY9_H_ - -#include "libGLESv2/renderer/QueryImpl.h" - -namespace rx -{ -class Renderer9; - -class Query9 : public QueryImpl -{ - public: - Query9(rx::Renderer9 *renderer, GLenum type); - virtual ~Query9(); - - void begin(); - void end(); - GLuint getResult(); - GLboolean isResultAvailable(); - - private: - DISALLOW_COPY_AND_ASSIGN(Query9); - - GLboolean testQuery(); - - rx::Renderer9 *mRenderer; - IDirect3DQuery9 *mQuery; -}; - -} - -#endif // LIBGLESV2_RENDERER_QUERY9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp deleted file mode 100644 index 090431db99..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.cpp +++ /dev/null @@ -1,113 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9 -// pointers retained by renderbuffers. - -#include "libGLESv2/renderer/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" - -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/main.h" - -namespace rx -{ - -RenderTarget9::RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface) -{ - mRenderer = Renderer9::makeRenderer9(renderer); - mRenderTarget = surface; - - if (mRenderTarget) - { - D3DSURFACE_DESC description; - mRenderTarget->GetDesc(&description); - - mWidth = description.Width; - mHeight = description.Height; - - mInternalFormat = d3d9_gl::GetEquivalentFormat(description.Format); - mActualFormat = d3d9_gl::GetEquivalentFormat(description.Format); - mSamples = d3d9_gl::GetSamplesFromMultisampleType(description.MultiSampleType); - } -} - -RenderTarget9::RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples) -{ - mRenderer = Renderer9::makeRenderer9(renderer); - mRenderTarget = NULL; - - D3DFORMAT requestedFormat = gl_d3d9::ConvertRenderbufferFormat(format); - int supportedSamples = mRenderer->getNearestSupportedSamples(requestedFormat, samples); - - if (supportedSamples == -1) - { - gl::error(GL_OUT_OF_MEMORY); - - return; - } - - HRESULT result = D3DERR_INVALIDCALL; - - if (width > 0 && height > 0) - { - if (requestedFormat == D3DFMT_D24S8) - { - result = mRenderer->getDevice()->CreateDepthStencilSurface(width, height, requestedFormat, - gl_d3d9::GetMultisampleTypeFromSamples(supportedSamples), - 0, FALSE, &mRenderTarget, NULL); - } - else - { - result = mRenderer->getDevice()->CreateRenderTarget(width, height, requestedFormat, - gl_d3d9::GetMultisampleTypeFromSamples(supportedSamples), - 0, FALSE, &mRenderTarget, NULL); - } - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY) - { - gl::error(GL_OUT_OF_MEMORY); - - return; - } - - ASSERT(SUCCEEDED(result)); - } - - mWidth = width; - mHeight = height; - mInternalFormat = format; - mSamples = supportedSamples; - mActualFormat = d3d9_gl::GetEquivalentFormat(requestedFormat); -} - -RenderTarget9::~RenderTarget9() -{ - if (mRenderTarget) - { - mRenderTarget->Release(); - } -} - -RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::RenderTarget9*, target)); - return static_cast(target); -} - -IDirect3DSurface9 *RenderTarget9::getSurface() -{ - // Caller is responsible for releasing the returned surface reference. - if (mRenderTarget) - { - mRenderTarget->AddRef(); - } - - return mRenderTarget; -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h deleted file mode 100644 index faf8ad1c6d..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/RenderTarget9.h +++ /dev/null @@ -1,40 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// RenderTarget9.h: Defines a D3D9-specific wrapper for IDirect3DSurface9 pointers -// retained by Renderbuffers. - -#ifndef LIBGLESV2_RENDERER_RENDERTARGET9_H_ -#define LIBGLESV2_RENDERER_RENDERTARGET9_H_ - -#include "libGLESv2/renderer/RenderTarget.h" - -namespace rx -{ -class Renderer; -class Renderer9; - -class RenderTarget9 : public RenderTarget -{ - public: - RenderTarget9(Renderer *renderer, IDirect3DSurface9 *surface); - RenderTarget9(Renderer *renderer, GLsizei width, GLsizei height, GLenum format, GLsizei samples); - virtual ~RenderTarget9(); - - static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget); - IDirect3DSurface9 *getSurface(); - - private: - DISALLOW_COPY_AND_ASSIGN(RenderTarget9); - - IDirect3DSurface9 *mRenderTarget; - - Renderer9 *mRenderer; -}; - -} - -#endif // LIBGLESV2_RENDERER_RENDERTARGET9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp deleted file mode 100644 index 97a10d64bf..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.cpp +++ /dev/null @@ -1,3287 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer. - -#include "libGLESv2/main.h" -#include "libGLESv2/Buffer.h" -#include "libGLESv2/Texture.h" -#include "libGLESv2/Framebuffer.h" -#include "libGLESv2/Renderbuffer.h" -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/renderer/IndexDataManager.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/ShaderExecutable9.h" -#include "libGLESv2/renderer/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d9/Image9.h" -#include "libGLESv2/renderer/d3d9/Blit.h" -#include "libGLESv2/renderer/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d9/VertexBuffer9.h" -#include "libGLESv2/renderer/d3d9/IndexBuffer9.h" -#include "libGLESv2/renderer/d3d9/BufferStorage9.h" -#include "libGLESv2/renderer/d3d9/Query9.h" -#include "libGLESv2/renderer/d3d9/Fence9.h" - -#include "libEGL/Display.h" - -#include "third_party/trace_event/trace_event.h" - -// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros -#define REF_RAST 0 - -// The "Debug This Pixel..." feature in PIX often fails when using the -// D3D9Ex interfaces. In order to get debug pixel to work on a Vista/Win 7 -// machine, define "ANGLE_ENABLE_D3D9EX=0" in your project file. -#if !defined(ANGLE_ENABLE_D3D9EX) -// Enables use of the IDirect3D9Ex interface, when available -#define ANGLE_ENABLE_D3D9EX 1 -#endif // !defined(ANGLE_ENABLE_D3D9EX) - -namespace rx -{ -static const D3DFORMAT RenderTargetFormats[] = - { - D3DFMT_A1R5G5B5, - // D3DFMT_A2R10G10B10, // The color_ramp conformance test uses ReadPixels with UNSIGNED_BYTE causing it to think that rendering skipped a colour value. - D3DFMT_A8R8G8B8, - D3DFMT_R5G6B5, - // D3DFMT_X1R5G5B5, // Has no compatible OpenGL ES renderbuffer format - D3DFMT_X8R8G8B8 - }; - -static const D3DFORMAT DepthStencilFormats[] = - { - D3DFMT_UNKNOWN, - // D3DFMT_D16_LOCKABLE, - D3DFMT_D32, - // D3DFMT_D15S1, - D3DFMT_D24S8, - D3DFMT_D24X8, - // D3DFMT_D24X4S4, - D3DFMT_D16, - // D3DFMT_D32F_LOCKABLE, - // D3DFMT_D24FS8 - }; - -enum -{ - MAX_VERTEX_CONSTANT_VECTORS_D3D9 = 256, - MAX_PIXEL_CONSTANT_VECTORS_SM2 = 32, - MAX_PIXEL_CONSTANT_VECTORS_SM3 = 224, - MAX_VARYING_VECTORS_SM2 = 8, - MAX_VARYING_VECTORS_SM3 = 10, - - MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4 -}; - -Renderer9::Renderer9(egl::Display *display, HDC hDc, bool softwareDevice) : Renderer(display), mDc(hDc), mSoftwareDevice(softwareDevice) -{ - mD3d9Module = NULL; - - mD3d9 = NULL; - mD3d9Ex = NULL; - mDevice = NULL; - mDeviceEx = NULL; - mDeviceWindow = NULL; - mBlit = NULL; - - mAdapter = D3DADAPTER_DEFAULT; - - #if REF_RAST == 1 || defined(FORCE_REF_RAST) - mDeviceType = D3DDEVTYPE_REF; - #else - mDeviceType = D3DDEVTYPE_HAL; - #endif - - mDeviceLost = false; - - mMaxSupportedSamples = 0; - - mMaskedClearSavedState = NULL; - - mVertexDataManager = NULL; - mIndexDataManager = NULL; - mLineLoopIB = NULL; - - mMaxNullColorbufferLRU = 0; - for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) - { - mNullColorbufferCache[i].lruCount = 0; - mNullColorbufferCache[i].width = 0; - mNullColorbufferCache[i].height = 0; - mNullColorbufferCache[i].buffer = NULL; - } -} - -Renderer9::~Renderer9() -{ - if (mDevice) - { - // If the device is lost, reset it first to prevent leaving the driver in an unstable state - if (testDeviceLost(false)) - { - resetDevice(); - } - } - - deinitialize(); -} - -void Renderer9::deinitialize() -{ - releaseDeviceResources(); - - SafeRelease(mDevice); - SafeRelease(mDeviceEx); - SafeRelease(mD3d9); - SafeRelease(mD3d9Ex); - - if (mDeviceWindow) - { - DestroyWindow(mDeviceWindow); - mDeviceWindow = NULL; - } - - if (mD3d9Module) - { - mD3d9Module = NULL; - } - - while (!mMultiSampleSupport.empty()) - { - delete [] mMultiSampleSupport.begin()->second; - mMultiSampleSupport.erase(mMultiSampleSupport.begin()); - } -} - -Renderer9 *Renderer9::makeRenderer9(Renderer *renderer) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::Renderer9*, renderer)); - return static_cast(renderer); -} - -EGLint Renderer9::initialize() -{ - if (!initializeCompiler()) - { - return EGL_NOT_INITIALIZED; - } - - if (mSoftwareDevice) - { - TRACE_EVENT0("gpu", "GetModuleHandle_swiftshader"); - mD3d9Module = GetModuleHandle(TEXT("swiftshader_d3d9.dll")); - } - else - { - TRACE_EVENT0("gpu", "GetModuleHandle_d3d9"); - mD3d9Module = GetModuleHandle(TEXT("d3d9.dll")); - } - - if (mD3d9Module == NULL) - { - ERR("No D3D9 module found - aborting!\n"); - return EGL_NOT_INITIALIZED; - } - - typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); - Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); - - // Use Direct3D9Ex if available. Among other things, this version is less - // inclined to report a lost context, for example when the user switches - // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available. - if (ANGLE_ENABLE_D3D9EX && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex))) - { - TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface"); - ASSERT(mD3d9Ex); - mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast(&mD3d9)); - ASSERT(mD3d9); - } - else - { - TRACE_EVENT0("gpu", "Direct3DCreate9"); - mD3d9 = Direct3DCreate9(D3D_SDK_VERSION); - } - - if (!mD3d9) - { - ERR("Could not create D3D9 device - aborting!\n"); - return EGL_NOT_INITIALIZED; - } - - if (mDc != NULL) - { - // UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to - } - - HRESULT result; - - // Give up on getting device caps after about one second. - { - TRACE_EVENT0("gpu", "GetDeviceCaps"); - for (int i = 0; i < 10; ++i) - { - result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps); - if (SUCCEEDED(result)) - { - break; - } - else if (result == D3DERR_NOTAVAILABLE) - { - Sleep(100); // Give the driver some time to initialize/recover - } - else if (FAILED(result)) // D3DERR_OUTOFVIDEOMEMORY, E_OUTOFMEMORY, D3DERR_INVALIDDEVICE, or another error we can't recover from - { - ERR("failed to get device caps (0x%x)\n", result); - return EGL_NOT_INITIALIZED; - } - } - } - - if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0)) - { - ERR("Renderer does not support PS 2.0. aborting!\n"); - return EGL_NOT_INITIALIZED; - } - - // When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported. - // This is required by Texture2D::convertToRenderTarget. - if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0) - { - ERR("Renderer does not support stretctrect from textures!\n"); - return EGL_NOT_INITIALIZED; - } - - { - TRACE_EVENT0("gpu", "GetAdapterIdentifier"); - mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier); - } - - // ATI cards on XP have problems with non-power-of-two textures. - mSupportsNonPower2Textures = !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) && - !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) && - !(mDeviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) && - !(getComparableOSVersion() < versionWindowsVista && mAdapterIdentifier.VendorId == VENDOR_ID_AMD); - - // Must support a minimum of 2:1 anisotropy for max anisotropy to be considered supported, per the spec - mSupportsTextureFilterAnisotropy = ((mDeviceCaps.RasterCaps & D3DPRASTERCAPS_ANISOTROPY) && (mDeviceCaps.MaxAnisotropy >= 2)); - - mMinSwapInterval = 4; - mMaxSwapInterval = 0; - - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) - { - mMinSwapInterval = std::min(mMinSwapInterval, 0); - mMaxSwapInterval = std::max(mMaxSwapInterval, 0); - } - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE) - { - mMinSwapInterval = std::min(mMinSwapInterval, 1); - mMaxSwapInterval = std::max(mMaxSwapInterval, 1); - } - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO) - { - mMinSwapInterval = std::min(mMinSwapInterval, 2); - mMaxSwapInterval = std::max(mMaxSwapInterval, 2); - } - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE) - { - mMinSwapInterval = std::min(mMinSwapInterval, 3); - mMaxSwapInterval = std::max(mMaxSwapInterval, 3); - } - if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR) - { - mMinSwapInterval = std::min(mMinSwapInterval, 4); - mMaxSwapInterval = std::max(mMaxSwapInterval, 4); - } - - int max = 0; - { - TRACE_EVENT0("gpu", "getMultiSampleSupport"); - for (unsigned int i = 0; i < ArraySize(RenderTargetFormats); ++i) - { - bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; - getMultiSampleSupport(RenderTargetFormats[i], multisampleArray); - mMultiSampleSupport[RenderTargetFormats[i]] = multisampleArray; - - for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) - { - if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) - { - max = j; - } - } - } - } - - { - TRACE_EVENT0("gpu", "getMultiSampleSupport2"); - for (unsigned int i = 0; i < ArraySize(DepthStencilFormats); ++i) - { - if (DepthStencilFormats[i] == D3DFMT_UNKNOWN) - continue; - - bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1]; - getMultiSampleSupport(DepthStencilFormats[i], multisampleArray); - mMultiSampleSupport[DepthStencilFormats[i]] = multisampleArray; - - for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j) - { - if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max) - { - max = j; - } - } - } - } - - mMaxSupportedSamples = max; - - static const TCHAR windowName[] = TEXT("AngleHiddenWindow"); - static const TCHAR className[] = TEXT("STATIC"); - - { - TRACE_EVENT0("gpu", "CreateWindowEx"); - mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL); - } - - D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); - DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES; - - { - TRACE_EVENT0("gpu", "D3d9_CreateDevice"); - result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice); - } - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST) - { - return EGL_BAD_ALLOC; - } - - if (FAILED(result)) - { - TRACE_EVENT0("gpu", "D3d9_CreateDevice2"); - result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST); - return EGL_BAD_ALLOC; - } - } - - if (mD3d9Ex) - { - TRACE_EVENT0("gpu", "mDevice_QueryInterface"); - result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**) &mDeviceEx); - ASSERT(SUCCEEDED(result)); - } - - { - TRACE_EVENT0("gpu", "ShaderCache initialize"); - mVertexShaderCache.initialize(mDevice); - mPixelShaderCache.initialize(mDevice); - } - - // Check occlusion query support - IDirect3DQuery9 *occlusionQuery = NULL; - { - TRACE_EVENT0("gpu", "device_CreateQuery"); - if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery)) && occlusionQuery) - { - occlusionQuery->Release(); - mOcclusionQuerySupport = true; - } - else - { - mOcclusionQuerySupport = false; - } - } - - // Check event query support - IDirect3DQuery9 *eventQuery = NULL; - { - TRACE_EVENT0("gpu", "device_CreateQuery2"); - if (SUCCEEDED(mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery)) && eventQuery) - { - eventQuery->Release(); - mEventQuerySupport = true; - } - else - { - mEventQuerySupport = false; - } - } - - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - // Check vertex texture support - // Only Direct3D 10 ready devices support all the necessary vertex texture formats. - // We test this using D3D9 by checking support for the R16F format. - mVertexTextureSupport = mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, - D3DUSAGE_QUERY_VERTEXTEXTURE, D3DRTYPE_TEXTURE, D3DFMT_R16F)); - - // Check depth texture support - // we use INTZ for depth textures in Direct3D9 - // we also want NULL texture support to ensure the we can make depth-only FBOs - // see http://aras-p.info/texts/D3D9GPUHacks.html - mDepthTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, - D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, D3DFMT_INTZ)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, - D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, D3DFMT_NULL)); - - // Check 32 bit floating point texture support - mFloat32FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, - D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, - D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); - - mFloat32RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); - - if (!mFloat32FilterSupport && !mFloat32RenderSupport) - { - mFloat32TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, - D3DRTYPE_TEXTURE, D3DFMT_A32B32G32R32F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, - D3DRTYPE_CUBETEXTURE, D3DFMT_A32B32G32R32F)); - } - else - { - mFloat32TextureSupport = true; - } - - // Check 16 bit floating point texture support - mFloat16FilterSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, - D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_QUERY_FILTER, - D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); - - mFloat16RenderSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, - D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); - - if (!mFloat16FilterSupport && !mFloat16RenderSupport) - { - mFloat16TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, - D3DRTYPE_TEXTURE, D3DFMT_A16B16G16R16F)) && - SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, - D3DRTYPE_CUBETEXTURE, D3DFMT_A16B16G16R16F)); - } - else - { - mFloat16TextureSupport = true; - } - - // Check DXT texture support - mDXT1TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT1)); - mDXT3TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT3)); - mDXT5TextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_DXT5)); - - // Check luminance[alpha] texture support - mLuminanceTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_L8)); - mLuminanceAlphaTextureSupport = SUCCEEDED(mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_A8L8)); - - initializeDevice(); - - return EGL_SUCCESS; -} - -// do any one-time device initialization -// NOTE: this is also needed after a device lost/reset -// to reset the scene status and ensure the default states are reset. -void Renderer9::initializeDevice() -{ - // Permanent non-default states - mDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); - mDevice->SetRenderState(D3DRS_LASTPIXEL, FALSE); - - if (mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0)) - { - mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, (DWORD&)mDeviceCaps.MaxPointSize); - } - else - { - mDevice->SetRenderState(D3DRS_POINTSIZE_MAX, 0x3F800000); // 1.0f - } - - markAllStateDirty(); - - mSceneStarted = false; - - ASSERT(!mBlit && !mVertexDataManager && !mIndexDataManager); - mBlit = new Blit(this); - mVertexDataManager = new rx::VertexDataManager(this); - mIndexDataManager = new rx::IndexDataManager(this); -} - -D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters() -{ - D3DPRESENT_PARAMETERS presentParameters = {0}; - - // The default swap chain is never actually used. Surface will create a new swap chain with the proper parameters. - presentParameters.AutoDepthStencilFormat = D3DFMT_UNKNOWN; - presentParameters.BackBufferCount = 1; - presentParameters.BackBufferFormat = D3DFMT_UNKNOWN; - presentParameters.BackBufferWidth = 1; - presentParameters.BackBufferHeight = 1; - presentParameters.EnableAutoDepthStencil = FALSE; - presentParameters.Flags = 0; - presentParameters.hDeviceWindow = mDeviceWindow; - presentParameters.MultiSampleQuality = 0; - presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; - presentParameters.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; - presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; - presentParameters.Windowed = TRUE; - - return presentParameters; -} - -int Renderer9::generateConfigs(ConfigDesc **configDescList) -{ - D3DDISPLAYMODE currentDisplayMode; - mD3d9->GetAdapterDisplayMode(mAdapter, ¤tDisplayMode); - - unsigned int numRenderFormats = ArraySize(RenderTargetFormats); - unsigned int numDepthFormats = ArraySize(DepthStencilFormats); - (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats]; - int numConfigs = 0; - - for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++) - { - D3DFORMAT renderTargetFormat = RenderTargetFormats[formatIndex]; - - HRESULT result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_RENDERTARGET, D3DRTYPE_SURFACE, renderTargetFormat); - - if (SUCCEEDED(result)) - { - for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++) - { - D3DFORMAT depthStencilFormat = DepthStencilFormats[depthStencilIndex]; - HRESULT result = D3D_OK; - - if(depthStencilFormat != D3DFMT_UNKNOWN) - { - result = mD3d9->CheckDeviceFormat(mAdapter, mDeviceType, currentDisplayMode.Format, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_SURFACE, depthStencilFormat); - } - - if (SUCCEEDED(result)) - { - if(depthStencilFormat != D3DFMT_UNKNOWN) - { - result = mD3d9->CheckDepthStencilMatch(mAdapter, mDeviceType, currentDisplayMode.Format, renderTargetFormat, depthStencilFormat); - } - - if (SUCCEEDED(result)) - { - ConfigDesc newConfig; - newConfig.renderTargetFormat = d3d9_gl::ConvertBackBufferFormat(renderTargetFormat); - newConfig.depthStencilFormat = d3d9_gl::ConvertDepthStencilFormat(depthStencilFormat); - newConfig.multiSample = 0; // FIXME: enumerate multi-sampling - newConfig.fastConfig = (currentDisplayMode.Format == renderTargetFormat); - - (*configDescList)[numConfigs++] = newConfig; - } - } - } - } - } - - return numConfigs; -} - -void Renderer9::deleteConfigs(ConfigDesc *configDescList) -{ - delete [] (configDescList); -} - -void Renderer9::startScene() -{ - if (!mSceneStarted) - { - long result = mDevice->BeginScene(); - if (SUCCEEDED(result)) { - // This is defensive checking against the device being - // lost at unexpected times. - mSceneStarted = true; - } - } -} - -void Renderer9::endScene() -{ - if (mSceneStarted) - { - // EndScene can fail if the device was lost, for example due - // to a TDR during a draw call. - mDevice->EndScene(); - mSceneStarted = false; - } -} - -void Renderer9::sync(bool block) -{ - HRESULT result; - - IDirect3DQuery9* query = allocateEventQuery(); - if (!query) - { - return; - } - - result = query->Issue(D3DISSUE_END); - ASSERT(SUCCEEDED(result)); - - do - { - result = query->GetData(NULL, 0, D3DGETDATA_FLUSH); - - if(block && result == S_FALSE) - { - // Keep polling, but allow other threads to do something useful first - Sleep(0); - // explicitly check for device loss - // some drivers seem to return S_FALSE even if the device is lost - // instead of D3DERR_DEVICELOST like they should - if (testDeviceLost(false)) - { - result = D3DERR_DEVICELOST; - } - } - } - while(block && result == S_FALSE); - - freeEventQuery(query); - - if (d3d9::isDeviceLostError(result)) - { - notifyDeviceLost(); - } -} - -SwapChain *Renderer9::createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) -{ - return new rx::SwapChain9(this, window, shareHandle, backBufferFormat, depthBufferFormat); -} - -IDirect3DQuery9* Renderer9::allocateEventQuery() -{ - IDirect3DQuery9 *query = NULL; - - if (mEventQueryPool.empty()) - { - HRESULT result = mDevice->CreateQuery(D3DQUERYTYPE_EVENT, &query); - ASSERT(SUCCEEDED(result)); - } - else - { - query = mEventQueryPool.back(); - mEventQueryPool.pop_back(); - } - - return query; -} - -void Renderer9::freeEventQuery(IDirect3DQuery9* query) -{ - if (mEventQueryPool.size() > 1000) - { - query->Release(); - } - else - { - mEventQueryPool.push_back(query); - } -} - -IDirect3DVertexShader9 *Renderer9::createVertexShader(const DWORD *function, size_t length) -{ - return mVertexShaderCache.create(function, length); -} - -IDirect3DPixelShader9 *Renderer9::createPixelShader(const DWORD *function, size_t length) -{ - return mPixelShaderCache.create(function, length); -} - -HRESULT Renderer9::createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer) -{ - D3DPOOL Pool = getBufferPool(Usage); - return mDevice->CreateVertexBuffer(Length, Usage, 0, Pool, ppVertexBuffer, NULL); -} - -VertexBuffer *Renderer9::createVertexBuffer() -{ - return new VertexBuffer9(this); -} - -HRESULT Renderer9::createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer) -{ - D3DPOOL Pool = getBufferPool(Usage); - return mDevice->CreateIndexBuffer(Length, Usage, Format, Pool, ppIndexBuffer, NULL); -} - -IndexBuffer *Renderer9::createIndexBuffer() -{ - return new IndexBuffer9(this); -} - -BufferStorage *Renderer9::createBufferStorage() -{ - return new BufferStorage9(); -} - -QueryImpl *Renderer9::createQuery(GLenum type) -{ - return new Query9(this, type); -} - -FenceImpl *Renderer9::createFence() -{ - return new Fence9(this); -} - -void Renderer9::setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &samplerState) -{ - bool *forceSetSamplers = (type == gl::SAMPLER_PIXEL) ? mForceSetPixelSamplerStates : mForceSetVertexSamplerStates; - gl::SamplerState *appliedSamplers = (type == gl::SAMPLER_PIXEL) ? mCurPixelSamplerStates: mCurVertexSamplerStates; - - if (forceSetSamplers[index] || memcmp(&samplerState, &appliedSamplers[index], sizeof(gl::SamplerState)) != 0) - { - int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; - int d3dSampler = index + d3dSamplerOffset; - - mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS)); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT)); - - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, gl_d3d9::ConvertMagFilter(samplerState.magFilter, samplerState.maxAnisotropy)); - D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter; - gl_d3d9::ConvertMinFilter(samplerState.minFilter, &d3dMinFilter, &d3dMipFilter, samplerState.maxAnisotropy); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter); - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXMIPLEVEL, samplerState.lodOffset); - if (mSupportsTextureFilterAnisotropy) - { - mDevice->SetSamplerState(d3dSampler, D3DSAMP_MAXANISOTROPY, (DWORD)samplerState.maxAnisotropy); - } - } - - forceSetSamplers[index] = false; - appliedSamplers[index] = samplerState; -} - -void Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *texture) -{ - int d3dSamplerOffset = (type == gl::SAMPLER_PIXEL) ? 0 : D3DVERTEXTEXTURESAMPLER0; - int d3dSampler = index + d3dSamplerOffset; - IDirect3DBaseTexture9 *d3dTexture = NULL; - unsigned int serial = 0; - bool forceSetTexture = false; - - unsigned int *appliedSerials = (type == gl::SAMPLER_PIXEL) ? mCurPixelTextureSerials : mCurVertexTextureSerials; - - if (texture) - { - TextureStorageInterface *texStorage = texture->getNativeTexture(); - if (texStorage) - { - TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage->getStorageInstance()); - d3dTexture = storage9->getBaseTexture(); - } - // If we get NULL back from getBaseTexture here, something went wrong - // in the texture class and we're unexpectedly missing the d3d texture - ASSERT(d3dTexture != NULL); - - serial = texture->getTextureSerial(); - forceSetTexture = texture->hasDirtyImages(); - } - - if (forceSetTexture || appliedSerials[index] != serial) - { - mDevice->SetTexture(d3dSampler, d3dTexture); - } - - appliedSerials[index] = serial; -} - -void Renderer9::setRasterizerState(const gl::RasterizerState &rasterState) -{ - bool rasterStateChanged = mForceSetRasterState || memcmp(&rasterState, &mCurRasterState, sizeof(gl::RasterizerState)) != 0; - - if (rasterStateChanged) - { - // Set the cull mode - if (rasterState.cullFace) - { - mDevice->SetRenderState(D3DRS_CULLMODE, gl_d3d9::ConvertCullMode(rasterState.cullMode, rasterState.frontFace)); - } - else - { - mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - } - - if (rasterState.polygonOffsetFill) - { - if (mCurDepthSize > 0) - { - mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *(DWORD*)&rasterState.polygonOffsetFactor); - - float depthBias = ldexp(rasterState.polygonOffsetUnits, -static_cast(mCurDepthSize)); - mDevice->SetRenderState(D3DRS_DEPTHBIAS, *(DWORD*)&depthBias); - } - } - else - { - mDevice->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0); - mDevice->SetRenderState(D3DRS_DEPTHBIAS, 0); - } - - mCurRasterState = rasterState; - } - - mForceSetRasterState = false; -} - -void Renderer9::setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, unsigned int sampleMask) -{ - bool blendStateChanged = mForceSetBlendState || memcmp(&blendState, &mCurBlendState, sizeof(gl::BlendState)) != 0; - bool blendColorChanged = mForceSetBlendState || memcmp(&blendColor, &mCurBlendColor, sizeof(gl::Color)) != 0; - bool sampleMaskChanged = mForceSetBlendState || sampleMask != mCurSampleMask; - - if (blendStateChanged || blendColorChanged) - { - if (blendState.blend) - { - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - - if (blendState.sourceBlendRGB != GL_CONSTANT_ALPHA && blendState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA && - blendState.destBlendRGB != GL_CONSTANT_ALPHA && blendState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA) - { - mDevice->SetRenderState(D3DRS_BLENDFACTOR, gl_d3d9::ConvertColor(blendColor)); - } - else - { - mDevice->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(gl::unorm<8>(blendColor.alpha), - gl::unorm<8>(blendColor.alpha), - gl::unorm<8>(blendColor.alpha), - gl::unorm<8>(blendColor.alpha))); - } - - mDevice->SetRenderState(D3DRS_SRCBLEND, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendRGB)); - mDevice->SetRenderState(D3DRS_DESTBLEND, gl_d3d9::ConvertBlendFunc(blendState.destBlendRGB)); - mDevice->SetRenderState(D3DRS_BLENDOP, gl_d3d9::ConvertBlendOp(blendState.blendEquationRGB)); - - if (blendState.sourceBlendRGB != blendState.sourceBlendAlpha || - blendState.destBlendRGB != blendState.destBlendAlpha || - blendState.blendEquationRGB != blendState.blendEquationAlpha) - { - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); - - mDevice->SetRenderState(D3DRS_SRCBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.sourceBlendAlpha)); - mDevice->SetRenderState(D3DRS_DESTBLENDALPHA, gl_d3d9::ConvertBlendFunc(blendState.destBlendAlpha)); - mDevice->SetRenderState(D3DRS_BLENDOPALPHA, gl_d3d9::ConvertBlendOp(blendState.blendEquationAlpha)); - } - else - { - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE); - } - } - else - { - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - } - - if (blendState.sampleAlphaToCoverage) - { - FIXME("Sample alpha to coverage is unimplemented."); - } - - // Set the color mask - bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD; - // Apparently some ATI cards have a bug where a draw with a zero color - // write mask can cause later draws to have incorrect results. Instead, - // set a nonzero color write mask but modify the blend state so that no - // drawing is done. - // http://code.google.com/p/angleproject/issues/detail?id=169 - - DWORD colorMask = gl_d3d9::ConvertColorMask(blendState.colorMaskRed, blendState.colorMaskGreen, - blendState.colorMaskBlue, blendState.colorMaskAlpha); - if (colorMask == 0 && !zeroColorMaskAllowed) - { - // Enable green channel, but set blending so nothing will be drawn. - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN); - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); - - mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO); - mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); - mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); - } - else - { - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask); - } - - mDevice->SetRenderState(D3DRS_DITHERENABLE, blendState.dither ? TRUE : FALSE); - - mCurBlendState = blendState; - mCurBlendColor = blendColor; - } - - if (sampleMaskChanged) - { - // Set the multisample mask - mDevice->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE); - mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, static_cast(sampleMask)); - - mCurSampleMask = sampleMask; - } - - mForceSetBlendState = false; -} - -void Renderer9::setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW) -{ - bool depthStencilStateChanged = mForceSetDepthStencilState || - memcmp(&depthStencilState, &mCurDepthStencilState, sizeof(gl::DepthStencilState)) != 0; - bool stencilRefChanged = mForceSetDepthStencilState || stencilRef != mCurStencilRef || - stencilBackRef != mCurStencilBackRef; - bool frontFaceCCWChanged = mForceSetDepthStencilState || frontFaceCCW != mCurFrontFaceCCW; - - if (depthStencilStateChanged) - { - if (depthStencilState.depthTest) - { - mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); - mDevice->SetRenderState(D3DRS_ZFUNC, gl_d3d9::ConvertComparison(depthStencilState.depthFunc)); - } - else - { - mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - } - - mCurDepthStencilState = depthStencilState; - } - - if (depthStencilStateChanged || stencilRefChanged || frontFaceCCWChanged) - { - if (depthStencilState.stencilTest && mCurStencilSize > 0) - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); - mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE); - - // FIXME: Unsupported by D3D9 - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF; - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK; - const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK; - if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || - stencilRef != stencilBackRef || - depthStencilState.stencilMask != depthStencilState.stencilBackMask) - { - ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL."); - return gl::error(GL_INVALID_OPERATION); - } - - // get the maximum size of the stencil ref - unsigned int maxStencil = (1 << mCurStencilSize) - 1; - - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, - depthStencilState.stencilWritemask); - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, - gl_d3d9::ConvertComparison(depthStencilState.stencilFunc)); - - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, - (stencilRef < (int)maxStencil) ? stencilRef : maxStencil); - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, - depthStencilState.stencilMask); - - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilFail)); - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthFail)); - mDevice->SetRenderState(frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilPassDepthPass)); - - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, - depthStencilState.stencilBackWritemask); - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC, - gl_d3d9::ConvertComparison(depthStencilState.stencilBackFunc)); - - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, - (stencilBackRef < (int)maxStencil) ? stencilBackRef : maxStencil); - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, - depthStencilState.stencilBackMask); - - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackFail)); - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthFail)); - mDevice->SetRenderState(!frontFaceCCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS, - gl_d3d9::ConvertStencilOp(depthStencilState.stencilBackPassDepthPass)); - } - else - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - } - - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, depthStencilState.depthMask ? TRUE : FALSE); - - mCurStencilRef = stencilRef; - mCurStencilBackRef = stencilBackRef; - mCurFrontFaceCCW = frontFaceCCW; - } - - mForceSetDepthStencilState = false; -} - -void Renderer9::setScissorRectangle(const gl::Rectangle &scissor, bool enabled) -{ - bool scissorChanged = mForceSetScissor || - memcmp(&scissor, &mCurScissor, sizeof(gl::Rectangle)) != 0 || - enabled != mScissorEnabled; - - if (scissorChanged) - { - if (enabled) - { - RECT rect; - rect.left = gl::clamp(scissor.x, 0, static_cast(mRenderTargetDesc.width)); - rect.top = gl::clamp(scissor.y, 0, static_cast(mRenderTargetDesc.height)); - rect.right = gl::clamp(scissor.x + scissor.width, 0, static_cast(mRenderTargetDesc.width)); - rect.bottom = gl::clamp(scissor.y + scissor.height, 0, static_cast(mRenderTargetDesc.height)); - mDevice->SetScissorRect(&rect); - } - - mDevice->SetRenderState(D3DRS_SCISSORTESTENABLE, enabled ? TRUE : FALSE); - - mScissorEnabled = enabled; - mCurScissor = scissor; - } - - mForceSetScissor = false; -} - -bool Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport) -{ - gl::Rectangle actualViewport = viewport; - float actualZNear = gl::clamp01(zNear); - float actualZFar = gl::clamp01(zFar); - if (ignoreViewport) - { - actualViewport.x = 0; - actualViewport.y = 0; - actualViewport.width = mRenderTargetDesc.width; - actualViewport.height = mRenderTargetDesc.height; - actualZNear = 0.0f; - actualZFar = 1.0f; - } - - D3DVIEWPORT9 dxViewport; - dxViewport.X = gl::clamp(actualViewport.x, 0, static_cast(mRenderTargetDesc.width)); - dxViewport.Y = gl::clamp(actualViewport.y, 0, static_cast(mRenderTargetDesc.height)); - dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast(mRenderTargetDesc.width) - static_cast(dxViewport.X)); - dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast(mRenderTargetDesc.height) - static_cast(dxViewport.Y)); - dxViewport.MinZ = actualZNear; - dxViewport.MaxZ = actualZFar; - - if (dxViewport.Width <= 0 || dxViewport.Height <= 0) - { - return false; // Nothing to render - } - - float depthFront = !gl::IsTriangleMode(drawMode) ? 0.0f : (frontFace == GL_CCW ? 1.0f : -1.0f); - - bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 || - actualZNear != mCurNear || actualZFar != mCurFar || mCurDepthFront != depthFront; - if (viewportChanged) - { - mDevice->SetViewport(&dxViewport); - - mCurViewport = actualViewport; - mCurNear = actualZNear; - mCurFar = actualZFar; - mCurDepthFront = depthFront; - - dx_VertexConstants vc = {0}; - dx_PixelConstants pc = {0}; - - vc.viewAdjust[0] = (float)((actualViewport.width - (int)dxViewport.Width) + 2 * (actualViewport.x - (int)dxViewport.X) - 1) / dxViewport.Width; - vc.viewAdjust[1] = (float)((actualViewport.height - (int)dxViewport.Height) + 2 * (actualViewport.y - (int)dxViewport.Y) - 1) / dxViewport.Height; - vc.viewAdjust[2] = (float)actualViewport.width / dxViewport.Width; - vc.viewAdjust[3] = (float)actualViewport.height / dxViewport.Height; - - pc.viewCoords[0] = actualViewport.width * 0.5f; - pc.viewCoords[1] = actualViewport.height * 0.5f; - pc.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f); - pc.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f); - - pc.depthFront[0] = (actualZFar - actualZNear) * 0.5f; - pc.depthFront[1] = (actualZNear + actualZFar) * 0.5f; - pc.depthFront[2] = depthFront; - - vc.depthRange[0] = actualZNear; - vc.depthRange[1] = actualZFar; - vc.depthRange[2] = actualZFar - actualZNear; - - pc.depthRange[0] = actualZNear; - pc.depthRange[1] = actualZFar; - pc.depthRange[2] = actualZFar - actualZNear; - - if (memcmp(&vc, &mVertexConstants, sizeof(dx_VertexConstants)) != 0) - { - mVertexConstants = vc; - mDxUniformsDirty = true; - } - - if (memcmp(&pc, &mPixelConstants, sizeof(dx_PixelConstants)) != 0) - { - mPixelConstants = pc; - mDxUniformsDirty = true; - } - } - - mForceSetViewport = false; - return true; -} - -bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count) -{ - switch (mode) - { - case GL_POINTS: - mPrimitiveType = D3DPT_POINTLIST; - mPrimitiveCount = count; - break; - case GL_LINES: - mPrimitiveType = D3DPT_LINELIST; - mPrimitiveCount = count / 2; - break; - case GL_LINE_LOOP: - mPrimitiveType = D3DPT_LINESTRIP; - mPrimitiveCount = count - 1; // D3D doesn't support line loops, so we draw the last line separately - break; - case GL_LINE_STRIP: - mPrimitiveType = D3DPT_LINESTRIP; - mPrimitiveCount = count - 1; - break; - case GL_TRIANGLES: - mPrimitiveType = D3DPT_TRIANGLELIST; - mPrimitiveCount = count / 3; - break; - case GL_TRIANGLE_STRIP: - mPrimitiveType = D3DPT_TRIANGLESTRIP; - mPrimitiveCount = count - 2; - break; - case GL_TRIANGLE_FAN: - mPrimitiveType = D3DPT_TRIANGLEFAN; - mPrimitiveCount = count - 2; - break; - default: - return gl::error(GL_INVALID_ENUM, false); - } - - return mPrimitiveCount > 0; -} - - -gl::Renderbuffer *Renderer9::getNullColorbuffer(gl::Renderbuffer *depthbuffer) -{ - if (!depthbuffer) - { - ERR("Unexpected null depthbuffer for depth-only FBO."); - return NULL; - } - - GLsizei width = depthbuffer->getWidth(); - GLsizei height = depthbuffer->getHeight(); - - // search cached nullcolorbuffers - for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) - { - if (mNullColorbufferCache[i].buffer != NULL && - mNullColorbufferCache[i].width == width && - mNullColorbufferCache[i].height == height) - { - mNullColorbufferCache[i].lruCount = ++mMaxNullColorbufferLRU; - return mNullColorbufferCache[i].buffer; - } - } - - gl::Renderbuffer *nullbuffer = new gl::Renderbuffer(this, 0, new gl::Colorbuffer(this, width, height, GL_NONE, 0)); - - // add nullbuffer to the cache - NullColorbufferCacheEntry *oldest = &mNullColorbufferCache[0]; - for (int i = 1; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) - { - if (mNullColorbufferCache[i].lruCount < oldest->lruCount) - { - oldest = &mNullColorbufferCache[i]; - } - } - - delete oldest->buffer; - oldest->buffer = nullbuffer; - oldest->lruCount = ++mMaxNullColorbufferLRU; - oldest->width = width; - oldest->height = height; - - return nullbuffer; -} - -bool Renderer9::applyRenderTarget(gl::Framebuffer *framebuffer) -{ - // if there is no color attachment we must synthesize a NULL colorattachment - // to keep the D3D runtime happy. This should only be possible if depth texturing. - gl::Renderbuffer *renderbufferObject = NULL; - if (framebuffer->getColorbufferType(0) != GL_NONE) - { - renderbufferObject = framebuffer->getColorbuffer(0); - } - else - { - renderbufferObject = getNullColorbuffer(framebuffer->getDepthbuffer()); - } - if (!renderbufferObject) - { - ERR("unable to locate renderbuffer for FBO."); - return false; - } - - bool renderTargetChanged = false; - unsigned int renderTargetSerial = renderbufferObject->getSerial(); - if (renderTargetSerial != mAppliedRenderTargetSerial) - { - // Apply the render target on the device - IDirect3DSurface9 *renderTargetSurface = NULL; - - RenderTarget *renderTarget = renderbufferObject->getRenderTarget(); - if (renderTarget) - { - renderTargetSurface = RenderTarget9::makeRenderTarget9(renderTarget)->getSurface(); - } - - if (!renderTargetSurface) - { - ERR("render target pointer unexpectedly null."); - return false; // Context must be lost - } - - mDevice->SetRenderTarget(0, renderTargetSurface); - renderTargetSurface->Release(); - - mAppliedRenderTargetSerial = renderTargetSerial; - renderTargetChanged = true; - } - - gl::Renderbuffer *depthStencil = NULL; - unsigned int depthbufferSerial = 0; - unsigned int stencilbufferSerial = 0; - if (framebuffer->getDepthbufferType() != GL_NONE) - { - depthStencil = framebuffer->getDepthbuffer(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - return false; - } - - depthbufferSerial = depthStencil->getSerial(); - } - else if (framebuffer->getStencilbufferType() != GL_NONE) - { - depthStencil = framebuffer->getStencilbuffer(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - return false; - } - - stencilbufferSerial = depthStencil->getSerial(); - } - - if (depthbufferSerial != mAppliedDepthbufferSerial || - stencilbufferSerial != mAppliedStencilbufferSerial || - !mDepthStencilInitialized) - { - unsigned int depthSize = 0; - unsigned int stencilSize = 0; - - // Apply the depth stencil on the device - if (depthStencil) - { - IDirect3DSurface9 *depthStencilSurface = NULL; - RenderTarget *depthStencilRenderTarget = depthStencil->getDepthStencil(); - - if (depthStencilRenderTarget) - { - depthStencilSurface = RenderTarget9::makeRenderTarget9(depthStencilRenderTarget)->getSurface(); - } - - if (!depthStencilSurface) - { - ERR("depth stencil pointer unexpectedly null."); - return false; // Context must be lost - } - - mDevice->SetDepthStencilSurface(depthStencilSurface); - depthStencilSurface->Release(); - - depthSize = depthStencil->getDepthSize(); - stencilSize = depthStencil->getStencilSize(); - } - else - { - mDevice->SetDepthStencilSurface(NULL); - } - - if (!mDepthStencilInitialized || depthSize != mCurDepthSize) - { - mCurDepthSize = depthSize; - mForceSetRasterState = true; - } - - if (!mDepthStencilInitialized || stencilSize != mCurStencilSize) - { - mCurStencilSize = stencilSize; - mForceSetDepthStencilState = true; - } - - mAppliedDepthbufferSerial = depthbufferSerial; - mAppliedStencilbufferSerial = stencilbufferSerial; - mDepthStencilInitialized = true; - } - - if (renderTargetChanged || !mRenderTargetDescInitialized) - { - mForceSetScissor = true; - mForceSetViewport = true; - - mRenderTargetDesc.width = renderbufferObject->getWidth(); - mRenderTargetDesc.height = renderbufferObject->getHeight(); - mRenderTargetDesc.format = renderbufferObject->getActualFormat(); - mRenderTargetDescInitialized = true; - } - - return true; -} - -GLenum Renderer9::applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances) -{ - TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS]; - GLenum err = mVertexDataManager->prepareVertexData(vertexAttributes, programBinary, first, count, attributes, instances); - if (err != GL_NO_ERROR) - { - return err; - } - - return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, programBinary, instances, &mRepeatDraw); -} - -// Applies the indices and element array bindings to the Direct3D 9 device -GLenum Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) -{ - GLenum err = mIndexDataManager->prepareIndexData(type, count, elementArrayBuffer, indices, indexInfo); - - if (err == GL_NO_ERROR) - { - // Directly binding the storage buffer is not supported for d3d9 - ASSERT(indexInfo->storage == NULL); - - if (indexInfo->serial != mAppliedIBSerial) - { - IndexBuffer9* indexBuffer = IndexBuffer9::makeIndexBuffer9(indexInfo->indexBuffer); - - mDevice->SetIndices(indexBuffer->getBuffer()); - mAppliedIBSerial = indexInfo->serial; - } - } - - return err; -} - -void Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances) -{ - startScene(); - - if (mode == GL_LINE_LOOP) - { - drawLineLoop(count, GL_NONE, NULL, 0, NULL); - } - else if (instances > 0) - { - StaticIndexBufferInterface *countingIB = mIndexDataManager->getCountingIndices(count); - if (countingIB) - { - if (mAppliedIBSerial != countingIB->getSerial()) - { - IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(countingIB->getIndexBuffer()); - - mDevice->SetIndices(indexBuffer->getBuffer()); - mAppliedIBSerial = countingIB->getSerial(); - } - - for (int i = 0; i < mRepeatDraw; i++) - { - mDevice->DrawIndexedPrimitive(mPrimitiveType, 0, 0, count, 0, mPrimitiveCount); - } - } - else - { - ERR("Could not create a counting index buffer for glDrawArraysInstanced."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - else // Regular case - { - mDevice->DrawPrimitive(mPrimitiveType, 0, mPrimitiveCount); - } -} - -void Renderer9::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei /*instances*/) -{ - startScene(); - - if (mode == GL_POINTS) - { - drawIndexedPoints(count, type, indices, indexInfo.minIndex, elementArrayBuffer); - } - else if (mode == GL_LINE_LOOP) - { - drawLineLoop(count, type, indices, indexInfo.minIndex, elementArrayBuffer); - } - else - { - for (int i = 0; i < mRepeatDraw; i++) - { - GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; - mDevice->DrawIndexedPrimitive(mPrimitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, mPrimitiveCount); - } - } -} - -void Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) -{ - // Get the raw indices for an indexed draw - if (type != GL_NONE && elementArrayBuffer) - { - gl::Buffer *indexBuffer = elementArrayBuffer; - BufferStorage *storage = indexBuffer->getStorage(); - intptr_t offset = reinterpret_cast(indices); - indices = static_cast(storage->getData()) + offset; - } - - unsigned int startIndex = 0; - - if (get32BitIndexSupport()) - { - if (!mLineLoopIB) - { - mLineLoopIB = new StreamingIndexBufferInterface(this); - if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT)) - { - delete mLineLoopIB; - mLineLoopIB = NULL; - - ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - - if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned int))) - { - ERR("Could not create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required."); - return gl::error(GL_OUT_OF_MEMORY); - } - - // Checked by Renderer9::applyPrimitiveType - ASSERT(count >= 0); - - const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned int); - if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT)) - { - ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - - void* mappedMemory = NULL; - unsigned int offset = 0; - if (!mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) - { - ERR("Could not map index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - - startIndex = static_cast(offset) / 4; - unsigned int *data = reinterpret_cast(mappedMemory); - - switch (type) - { - case GL_NONE: // Non-indexed draw - for (int i = 0; i < count; i++) - { - data[i] = i; - } - data[count] = 0; - break; - case GL_UNSIGNED_BYTE: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_SHORT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_INT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - default: UNREACHABLE(); - } - - if (!mLineLoopIB->unmapBuffer()) - { - ERR("Could not unmap index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - else - { - if (!mLineLoopIB) - { - mLineLoopIB = new StreamingIndexBufferInterface(this); - if (!mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT)) - { - delete mLineLoopIB; - mLineLoopIB = NULL; - - ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - - // Checked by Renderer9::applyPrimitiveType - ASSERT(count >= 0); - - if (static_cast(count) + 1 > (std::numeric_limits::max() / sizeof(unsigned short))) - { - ERR("Could not create a 16-bit looping index buffer for GL_LINE_LOOP, too many indices required."); - return gl::error(GL_OUT_OF_MEMORY); - } - - const unsigned int spaceNeeded = (static_cast(count) + 1) * sizeof(unsigned short); - if (!mLineLoopIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_SHORT)) - { - ERR("Could not reserve enough space in looping index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - - void* mappedMemory = NULL; - unsigned int offset; - if (mLineLoopIB->mapBuffer(spaceNeeded, &mappedMemory, &offset)) - { - ERR("Could not map index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - - startIndex = static_cast(offset) / 2; - unsigned short *data = reinterpret_cast(mappedMemory); - - switch (type) - { - case GL_NONE: // Non-indexed draw - for (int i = 0; i < count; i++) - { - data[i] = i; - } - data[count] = 0; - break; - case GL_UNSIGNED_BYTE: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_SHORT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - case GL_UNSIGNED_INT: - for (int i = 0; i < count; i++) - { - data[i] = static_cast(indices)[i]; - } - data[count] = static_cast(indices)[0]; - break; - default: UNREACHABLE(); - } - - if (!mLineLoopIB->unmapBuffer()) - { - ERR("Could not unmap index buffer for GL_LINE_LOOP."); - return gl::error(GL_OUT_OF_MEMORY); - } - } - - if (mAppliedIBSerial != mLineLoopIB->getSerial()) - { - IndexBuffer9 *indexBuffer = IndexBuffer9::makeIndexBuffer9(mLineLoopIB->getIndexBuffer()); - - mDevice->SetIndices(indexBuffer->getBuffer()); - mAppliedIBSerial = mLineLoopIB->getSerial(); - } - - mDevice->DrawIndexedPrimitive(D3DPT_LINESTRIP, -minIndex, minIndex, count, startIndex, count); -} - -template -static void drawPoints(IDirect3DDevice9* device, GLsizei count, const GLvoid *indices, int minIndex) -{ - for (int i = 0; i < count; i++) - { - unsigned int indexValue = static_cast(static_cast(indices)[i]) - minIndex; - device->DrawPrimitive(D3DPT_POINTLIST, indexValue, 1); - } -} - -void Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer) -{ - // Drawing index point lists is unsupported in d3d9, fall back to a regular DrawPrimitive call - // for each individual point. This call is not expected to happen often. - - if (elementArrayBuffer) - { - BufferStorage *storage = elementArrayBuffer->getStorage(); - intptr_t offset = reinterpret_cast(indices); - indices = static_cast(storage->getData()) + offset; - } - - switch (type) - { - case GL_UNSIGNED_BYTE: drawPoints(mDevice, count, indices, minIndex); break; - case GL_UNSIGNED_SHORT: drawPoints(mDevice, count, indices, minIndex); break; - case GL_UNSIGNED_INT: drawPoints(mDevice, count, indices, minIndex); break; - default: UNREACHABLE(); - } -} - -void Renderer9::applyShaders(gl::ProgramBinary *programBinary) -{ - unsigned int programBinarySerial = programBinary->getSerial(); - if (programBinarySerial != mAppliedProgramBinarySerial) - { - ShaderExecutable *vertexExe = programBinary->getVertexExecutable(); - ShaderExecutable *pixelExe = programBinary->getPixelExecutable(); - - IDirect3DVertexShader9 *vertexShader = NULL; - if (vertexExe) vertexShader = ShaderExecutable9::makeShaderExecutable9(vertexExe)->getVertexShader(); - - IDirect3DPixelShader9 *pixelShader = NULL; - if (pixelExe) pixelShader = ShaderExecutable9::makeShaderExecutable9(pixelExe)->getPixelShader(); - - mDevice->SetPixelShader(pixelShader); - mDevice->SetVertexShader(vertexShader); - programBinary->dirtyAllUniforms(); - mDxUniformsDirty = true; - - mAppliedProgramBinarySerial = programBinarySerial; - } -} - -void Renderer9::applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray) -{ - for (std::vector::const_iterator ub = uniformArray->begin(), ue = uniformArray->end(); ub != ue; ++ub) - { - gl::Uniform *targetUniform = *ub; - - if (targetUniform->dirty) - { - GLfloat *f = (GLfloat*)targetUniform->data; - GLint *i = (GLint*)targetUniform->data; - - switch (targetUniform->type) - { - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - break; - case GL_BOOL: - case GL_BOOL_VEC2: - case GL_BOOL_VEC3: - case GL_BOOL_VEC4: - applyUniformnbv(targetUniform, i); - break; - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT4: - applyUniformnfv(targetUniform, f); - break; - case GL_INT: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: - applyUniformniv(targetUniform, i); - break; - default: - UNREACHABLE(); - } - - targetUniform->dirty = false; - } - } - - // Driver uniforms - if (mDxUniformsDirty) - { - mDevice->SetVertexShaderConstantF(0, (float*)&mVertexConstants, sizeof(dx_VertexConstants) / sizeof(float[4])); - mDevice->SetPixelShaderConstantF(0, (float*)&mPixelConstants, sizeof(dx_PixelConstants) / sizeof(float[4])); - mDxUniformsDirty = false; - } -} - -void Renderer9::applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v) -{ - if (targetUniform->psRegisterIndex >= 0) - { - mDevice->SetPixelShaderConstantF(targetUniform->psRegisterIndex, v, targetUniform->registerCount); - } - - if (targetUniform->vsRegisterIndex >= 0) - { - mDevice->SetVertexShaderConstantF(targetUniform->vsRegisterIndex, v, targetUniform->registerCount); - } -} - -void Renderer9::applyUniformniv(gl::Uniform *targetUniform, const GLint *v) -{ - ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); - GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; - - for (unsigned int i = 0; i < targetUniform->registerCount; i++) - { - vector[i][0] = (GLfloat)v[4 * i + 0]; - vector[i][1] = (GLfloat)v[4 * i + 1]; - vector[i][2] = (GLfloat)v[4 * i + 2]; - vector[i][3] = (GLfloat)v[4 * i + 3]; - } - - applyUniformnfv(targetUniform, (GLfloat*)vector); -} - -void Renderer9::applyUniformnbv(gl::Uniform *targetUniform, const GLint *v) -{ - ASSERT(targetUniform->registerCount <= MAX_VERTEX_CONSTANT_VECTORS_D3D9); - GLfloat vector[MAX_VERTEX_CONSTANT_VECTORS_D3D9][4]; - - for (unsigned int i = 0; i < targetUniform->registerCount; i++) - { - vector[i][0] = (v[4 * i + 0] == GL_FALSE) ? 0.0f : 1.0f; - vector[i][1] = (v[4 * i + 1] == GL_FALSE) ? 0.0f : 1.0f; - vector[i][2] = (v[4 * i + 2] == GL_FALSE) ? 0.0f : 1.0f; - vector[i][3] = (v[4 * i + 3] == GL_FALSE) ? 0.0f : 1.0f; - } - - applyUniformnfv(targetUniform, (GLfloat*)vector); -} - -void Renderer9::clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer) -{ - D3DCOLOR color = D3DCOLOR_ARGB(gl::unorm<8>(clearParams.colorClearValue.alpha), - gl::unorm<8>(clearParams.colorClearValue.red), - gl::unorm<8>(clearParams.colorClearValue.green), - gl::unorm<8>(clearParams.colorClearValue.blue)); - float depth = gl::clamp01(clearParams.depthClearValue); - int stencil = clearParams.stencilClearValue & 0x000000FF; - - unsigned int stencilUnmasked = 0x0; - if ((clearParams.mask & GL_STENCIL_BUFFER_BIT) && frameBuffer->hasStencil()) - { - unsigned int stencilSize = gl::GetStencilSize(frameBuffer->getStencilbuffer()->getActualFormat()); - stencilUnmasked = (0x1 << stencilSize) - 1; - } - - bool alphaUnmasked = (gl::GetAlphaSize(mRenderTargetDesc.format) == 0) || clearParams.colorMaskAlpha; - - const bool needMaskedStencilClear = (clearParams.mask & GL_STENCIL_BUFFER_BIT) && - (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked; - const bool needMaskedColorClear = (clearParams.mask & GL_COLOR_BUFFER_BIT) && - !(clearParams.colorMaskRed && clearParams.colorMaskGreen && - clearParams.colorMaskBlue && alphaUnmasked); - - if (needMaskedColorClear || needMaskedStencilClear) - { - // State which is altered in all paths from this point to the clear call is saved. - // State which is altered in only some paths will be flagged dirty in the case that - // that path is taken. - HRESULT hr; - if (mMaskedClearSavedState == NULL) - { - hr = mDevice->BeginStateBlock(); - ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); - - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); - mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); - mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); - mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - mDevice->SetPixelShader(NULL); - mDevice->SetVertexShader(NULL); - mDevice->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE); - mDevice->SetStreamSource(0, NULL, 0, 0); - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); - mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); - mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); - mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); - mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); - - for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mDevice->SetStreamSourceFreq(i, 1); - } - - hr = mDevice->EndStateBlock(&mMaskedClearSavedState); - ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY); - } - - ASSERT(mMaskedClearSavedState != NULL); - - if (mMaskedClearSavedState != NULL) - { - hr = mMaskedClearSavedState->Capture(); - ASSERT(SUCCEEDED(hr)); - } - - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, FALSE); - mDevice->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); - mDevice->SetRenderState(D3DRS_ZENABLE, FALSE); - mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - mDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - mDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - mDevice->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - - if (clearParams.mask & GL_COLOR_BUFFER_BIT) - { - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, - gl_d3d9::ConvertColorMask(clearParams.colorMaskRed, - clearParams.colorMaskGreen, - clearParams.colorMaskBlue, - clearParams.colorMaskAlpha)); - } - else - { - mDevice->SetRenderState(D3DRS_COLORWRITEENABLE, 0); - } - - if (stencilUnmasked != 0x0 && (clearParams.mask & GL_STENCIL_BUFFER_BIT)) - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, TRUE); - mDevice->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE); - mDevice->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS); - mDevice->SetRenderState(D3DRS_STENCILREF, stencil); - mDevice->SetRenderState(D3DRS_STENCILWRITEMASK, clearParams.stencilWriteMask); - mDevice->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE); - mDevice->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE); - mDevice->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE); - } - else - { - mDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE); - } - - mDevice->SetPixelShader(NULL); - mDevice->SetVertexShader(NULL); - mDevice->SetFVF(D3DFVF_XYZRHW); - mDevice->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE); - mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR); - mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR); - mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, color); - mDevice->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF); - - for(int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mDevice->SetStreamSourceFreq(i, 1); - } - - float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges - quad[0][0] = -0.5f; - quad[0][1] = mRenderTargetDesc.height - 0.5f; - quad[0][2] = 0.0f; - quad[0][3] = 1.0f; - - quad[1][0] = mRenderTargetDesc.width - 0.5f; - quad[1][1] = mRenderTargetDesc.height - 0.5f; - quad[1][2] = 0.0f; - quad[1][3] = 1.0f; - - quad[2][0] = -0.5f; - quad[2][1] = -0.5f; - quad[2][2] = 0.0f; - quad[2][3] = 1.0f; - - quad[3][0] = mRenderTargetDesc.width - 0.5f; - quad[3][1] = -0.5f; - quad[3][2] = 0.0f; - quad[3][3] = 1.0f; - - startScene(); - mDevice->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4])); - - if (clearParams.mask & GL_DEPTH_BUFFER_BIT) - { - mDevice->SetRenderState(D3DRS_ZENABLE, TRUE); - mDevice->SetRenderState(D3DRS_ZWRITEENABLE, TRUE); - mDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil); - } - - if (mMaskedClearSavedState != NULL) - { - mMaskedClearSavedState->Apply(); - } - } - else if (clearParams.mask) - { - DWORD dxClearFlags = 0; - if (clearParams.mask & GL_COLOR_BUFFER_BIT) - { - dxClearFlags |= D3DCLEAR_TARGET; - } - if (clearParams.mask & GL_DEPTH_BUFFER_BIT) - { - dxClearFlags |= D3DCLEAR_ZBUFFER; - } - if (clearParams.mask & GL_STENCIL_BUFFER_BIT) - { - dxClearFlags |= D3DCLEAR_STENCIL; - } - - mDevice->Clear(0, NULL, dxClearFlags, color, depth, stencil); - } -} - -void Renderer9::markAllStateDirty() -{ - mAppliedRenderTargetSerial = 0; - mAppliedDepthbufferSerial = 0; - mAppliedStencilbufferSerial = 0; - mDepthStencilInitialized = false; - mRenderTargetDescInitialized = false; - - mForceSetDepthStencilState = true; - mForceSetRasterState = true; - mForceSetScissor = true; - mForceSetViewport = true; - mForceSetBlendState = true; - - for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS; i++) - { - mForceSetVertexSamplerStates[i] = true; - mCurVertexTextureSerials[i] = 0; - } - for (unsigned int i = 0; i < gl::MAX_TEXTURE_IMAGE_UNITS; i++) - { - mForceSetPixelSamplerStates[i] = true; - mCurPixelTextureSerials[i] = 0; - } - - mAppliedIBSerial = 0; - mAppliedProgramBinarySerial = 0; - mDxUniformsDirty = true; - - mVertexDeclarationCache.markStateDirty(); -} - -void Renderer9::releaseDeviceResources() -{ - while (!mEventQueryPool.empty()) - { - mEventQueryPool.back()->Release(); - mEventQueryPool.pop_back(); - } - - SafeRelease(mMaskedClearSavedState); - - mVertexShaderCache.clear(); - mPixelShaderCache.clear(); - - SafeDelete(mBlit); - SafeDelete(mVertexDataManager); - SafeDelete(mIndexDataManager); - SafeDelete(mLineLoopIB); - - for (int i = 0; i < NUM_NULL_COLORBUFFER_CACHE_ENTRIES; i++) - { - SafeDelete(mNullColorbufferCache[i].buffer); - } - -} - - -void Renderer9::notifyDeviceLost() -{ - mDeviceLost = true; - mDisplay->notifyDeviceLost(); -} - -bool Renderer9::isDeviceLost() -{ - return mDeviceLost; -} - -// set notify to true to broadcast a message to all contexts of the device loss -bool Renderer9::testDeviceLost(bool notify) -{ - HRESULT status = getDeviceStatusCode(); - bool isLost = FAILED(status); - - if (isLost) - { - // ensure we note the device loss -- - // we'll probably get this done again by notifyDeviceLost - // but best to remember it! - // Note that we don't want to clear the device loss status here - // -- this needs to be done by resetDevice - mDeviceLost = true; - if (notify) - { - notifyDeviceLost(); - } - } - - return isLost; -} - -HRESULT Renderer9::getDeviceStatusCode() -{ - HRESULT status = D3D_OK; - - if (mDeviceEx) - { - status = mDeviceEx->CheckDeviceState(NULL); - } - else if (mDevice) - { - status = mDevice->TestCooperativeLevel(); - } - - return status; -} - -bool Renderer9::testDeviceResettable() -{ - // On D3D9Ex, DEVICELOST represents a hung device that needs to be restarted - // DEVICEREMOVED indicates the device has been stopped and must be recreated - switch (getDeviceStatusCode()) - { - case D3DERR_DEVICENOTRESET: - case D3DERR_DEVICEHUNG: - return true; - case D3DERR_DEVICELOST: - return (mDeviceEx != NULL); - case D3DERR_DEVICEREMOVED: - ASSERT(mDeviceEx != NULL); - return isRemovedDeviceResettable(); - default: - return false; - } -} - -bool Renderer9::resetDevice() -{ - releaseDeviceResources(); - - D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters(); - - HRESULT result = D3D_OK; - bool lost = testDeviceLost(false); - bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED); - - // Device Removed is a feature which is only present with D3D9Ex - ASSERT(mDeviceEx != NULL || !removedDevice); - - for (int attempts = 3; lost && attempts > 0; attempts--) - { - if (removedDevice) - { - // Device removed, which may trigger on driver reinstallation, - // may cause a longer wait other reset attempts before the - // system is ready to handle creating a new device. - Sleep(800); - lost = !resetRemovedDevice(); - } - else if (mDeviceEx) - { - Sleep(500); // Give the graphics driver some CPU time - result = mDeviceEx->ResetEx(&presentParameters, NULL); - lost = testDeviceLost(false); - } - else - { - result = mDevice->TestCooperativeLevel(); - while (result == D3DERR_DEVICELOST) - { - Sleep(100); // Give the graphics driver some CPU time - result = mDevice->TestCooperativeLevel(); - } - - if (result == D3DERR_DEVICENOTRESET) - { - result = mDevice->Reset(&presentParameters); - } - lost = testDeviceLost(false); - } - } - - if (FAILED(result)) - { - ERR("Reset/ResetEx failed multiple times: 0x%08X", result); - return false; - } - - if (removedDevice && lost) - { - ERR("Device lost reset failed multiple times"); - return false; - } - - // If the device was removed, we already finished re-initialization in resetRemovedDevice - if (!removedDevice) - { - // reset device defaults - initializeDevice(); - } - - mDeviceLost = false; - - return true; -} - -bool Renderer9::isRemovedDeviceResettable() const -{ - bool success = false; - -#ifdef ANGLE_ENABLE_D3D9EX - IDirect3D9Ex *d3d9Ex = NULL; - typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**); - Direct3DCreate9ExFunc Direct3DCreate9ExPtr = reinterpret_cast(GetProcAddress(mD3d9Module, "Direct3DCreate9Ex")); - - if (Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &d3d9Ex))) - { - D3DCAPS9 deviceCaps; - HRESULT result = d3d9Ex->GetDeviceCaps(mAdapter, mDeviceType, &deviceCaps); - success = SUCCEEDED(result); - } - - SafeRelease(d3d9Ex); -#else - ASSERT(UNREACHABLE()); -#endif - - return success; -} - -bool Renderer9::resetRemovedDevice() -{ - // From http://msdn.microsoft.com/en-us/library/windows/desktop/bb172554(v=vs.85).aspx: - // The hardware adapter has been removed. Application must destroy the device, do enumeration of - // adapters and create another Direct3D device. If application continues rendering without - // calling Reset, the rendering calls will succeed. Applies to Direct3D 9Ex only. - deinitialize(); - return (initialize() == EGL_SUCCESS); -} - -DWORD Renderer9::getAdapterVendor() const -{ - return mAdapterIdentifier.VendorId; -} - -std::string Renderer9::getRendererDescription() const -{ - std::ostringstream rendererString; - - rendererString << mAdapterIdentifier.Description; - if (getShareHandleSupport()) - { - rendererString << " Direct3D9Ex"; - } - else - { - rendererString << " Direct3D9"; - } - - rendererString << " vs_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.VertexShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.VertexShaderVersion); - rendererString << " ps_" << D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion) << "_" << D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion); - - return rendererString.str(); -} - -GUID Renderer9::getAdapterIdentifier() const -{ - return mAdapterIdentifier.DeviceIdentifier; -} - -void Renderer9::getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray) -{ - for (int multiSampleIndex = 0; multiSampleIndex <= D3DMULTISAMPLE_16_SAMPLES; multiSampleIndex++) - { - HRESULT result = mD3d9->CheckDeviceMultiSampleType(mAdapter, mDeviceType, format, - TRUE, (D3DMULTISAMPLE_TYPE)multiSampleIndex, NULL); - - multiSampleArray[multiSampleIndex] = SUCCEEDED(result); - } -} - -bool Renderer9::getBGRATextureSupport() const -{ - // DirectX 9 always supports BGRA - return true; -} - -bool Renderer9::getDXT1TextureSupport() -{ - return mDXT1TextureSupport; -} - -bool Renderer9::getDXT3TextureSupport() -{ - return mDXT3TextureSupport; -} - -bool Renderer9::getDXT5TextureSupport() -{ - return mDXT5TextureSupport; -} - -bool Renderer9::getDepthTextureSupport() const -{ - return mDepthTextureSupport; -} - -bool Renderer9::getFloat32TextureSupport(bool *filtering, bool *renderable) -{ - *filtering = mFloat32FilterSupport; - *renderable = mFloat32RenderSupport; - return mFloat32TextureSupport; -} - -bool Renderer9::getFloat16TextureSupport(bool *filtering, bool *renderable) -{ - *filtering = mFloat16FilterSupport; - *renderable = mFloat16RenderSupport; - return mFloat16TextureSupport; -} - -bool Renderer9::getLuminanceTextureSupport() -{ - return mLuminanceTextureSupport; -} - -bool Renderer9::getLuminanceAlphaTextureSupport() -{ - return mLuminanceAlphaTextureSupport; -} - -bool Renderer9::getTextureFilterAnisotropySupport() const -{ - return mSupportsTextureFilterAnisotropy; -} - -float Renderer9::getTextureMaxAnisotropy() const -{ - if (mSupportsTextureFilterAnisotropy) - { - return static_cast(mDeviceCaps.MaxAnisotropy); - } - return 1.0f; -} - -bool Renderer9::getEventQuerySupport() -{ - return mEventQuerySupport; -} - -unsigned int Renderer9::getMaxVertexTextureImageUnits() const -{ - META_ASSERT(MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 <= gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS); - return mVertexTextureSupport ? MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 : 0; -} - -unsigned int Renderer9::getMaxCombinedTextureImageUnits() const -{ - return gl::MAX_TEXTURE_IMAGE_UNITS + getMaxVertexTextureImageUnits(); -} - -unsigned int Renderer9::getReservedVertexUniformVectors() const -{ - return 2; // dx_ViewAdjust and dx_DepthRange. -} - -unsigned int Renderer9::getReservedFragmentUniformVectors() const -{ - return 3; // dx_ViewCoords, dx_DepthFront and dx_DepthRange. -} - -unsigned int Renderer9::getMaxVertexUniformVectors() const -{ - return MAX_VERTEX_CONSTANT_VECTORS_D3D9 - getReservedVertexUniformVectors(); -} - -unsigned int Renderer9::getMaxFragmentUniformVectors() const -{ - const int maxPixelConstantVectors = (getMajorShaderModel() >= 3) ? MAX_PIXEL_CONSTANT_VECTORS_SM3 : MAX_PIXEL_CONSTANT_VECTORS_SM2; - - return maxPixelConstantVectors - getReservedFragmentUniformVectors(); -} - -unsigned int Renderer9::getMaxVaryingVectors() const -{ - return (getMajorShaderModel() >= 3) ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2; -} - -bool Renderer9::getNonPower2TextureSupport() const -{ - return mSupportsNonPower2Textures; -} - -bool Renderer9::getOcclusionQuerySupport() const -{ - return mOcclusionQuerySupport; -} - -bool Renderer9::getInstancingSupport() const -{ - return mDeviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0); -} - -bool Renderer9::getShareHandleSupport() const -{ - // PIX doesn't seem to support using share handles, so disable them. - return (mD3d9Ex != NULL) && !gl::perfActive(); -} - -bool Renderer9::getDerivativeInstructionSupport() const -{ - return (mDeviceCaps.PS20Caps.Caps & D3DPS20CAPS_GRADIENTINSTRUCTIONS) != 0; -} - -bool Renderer9::getPostSubBufferSupport() const -{ - return true; -} - -int Renderer9::getMajorShaderModel() const -{ - return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion); -} - -float Renderer9::getMaxPointSize() const -{ - // Point size clamped at 1.0f for SM2 - return getMajorShaderModel() == 3 ? mDeviceCaps.MaxPointSize : 1.0f; -} - -int Renderer9::getMaxViewportDimension() const -{ - int maxTextureDimension = std::min(std::min(getMaxTextureWidth(), getMaxTextureHeight()), - (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE); - return maxTextureDimension; -} - -int Renderer9::getMaxTextureWidth() const -{ - return (int)mDeviceCaps.MaxTextureWidth; -} - -int Renderer9::getMaxTextureHeight() const -{ - return (int)mDeviceCaps.MaxTextureHeight; -} - -bool Renderer9::get32BitIndexSupport() const -{ - return mDeviceCaps.MaxVertexIndex >= (1 << 16); -} - -DWORD Renderer9::getCapsDeclTypes() const -{ - return mDeviceCaps.DeclTypes; -} - -int Renderer9::getMinSwapInterval() const -{ - return mMinSwapInterval; -} - -int Renderer9::getMaxSwapInterval() const -{ - return mMaxSwapInterval; -} - -int Renderer9::getMaxSupportedSamples() const -{ - return mMaxSupportedSamples; -} - -int Renderer9::getNearestSupportedSamples(D3DFORMAT format, int requested) const -{ - if (requested == 0) - { - return requested; - } - - std::map::const_iterator itr = mMultiSampleSupport.find(format); - if (itr == mMultiSampleSupport.end()) - { - if (format == D3DFMT_UNKNOWN) - return 0; - return -1; - } - - for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i) - { - if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE) - { - return i; - } - } - - return -1; -} - -unsigned int Renderer9::getMaxRenderTargets() const -{ - // we do not support MRT in d3d9 - return 1; -} - -D3DFORMAT Renderer9::ConvertTextureInternalFormat(GLint internalformat) -{ - switch (internalformat) - { - case GL_DEPTH_COMPONENT16: - case GL_DEPTH_COMPONENT32_OES: - case GL_DEPTH24_STENCIL8_OES: - return D3DFMT_INTZ; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - return D3DFMT_DXT1; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - return D3DFMT_DXT3; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - return D3DFMT_DXT5; - case GL_RGBA32F_EXT: - case GL_RGB32F_EXT: - case GL_ALPHA32F_EXT: - case GL_LUMINANCE32F_EXT: - case GL_LUMINANCE_ALPHA32F_EXT: - return D3DFMT_A32B32G32R32F; - case GL_RGBA16F_EXT: - case GL_RGB16F_EXT: - case GL_ALPHA16F_EXT: - case GL_LUMINANCE16F_EXT: - case GL_LUMINANCE_ALPHA16F_EXT: - return D3DFMT_A16B16G16R16F; - case GL_LUMINANCE8_EXT: - if (getLuminanceTextureSupport()) - { - return D3DFMT_L8; - } - break; - case GL_LUMINANCE8_ALPHA8_EXT: - if (getLuminanceAlphaTextureSupport()) - { - return D3DFMT_A8L8; - } - break; - case GL_RGB8_OES: - case GL_RGB565: - return D3DFMT_X8R8G8B8; - } - - return D3DFMT_A8R8G8B8; -} - -bool Renderer9::copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source) -{ - bool result = false; - - if (source && dest) - { - TextureStorage9_2D *source9 = TextureStorage9_2D::makeTextureStorage9_2D(source->getStorageInstance()); - TextureStorage9_2D *dest9 = TextureStorage9_2D::makeTextureStorage9_2D(dest->getStorageInstance()); - - int levels = source9->levelCount(); - for (int i = 0; i < levels; ++i) - { - IDirect3DSurface9 *srcSurf = source9->getSurfaceLevel(i, false); - IDirect3DSurface9 *dstSurf = dest9->getSurfaceLevel(i, false); - - result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); - - if (srcSurf) srcSurf->Release(); - if (dstSurf) dstSurf->Release(); - - if (!result) - return false; - } - } - - return result; -} - -bool Renderer9::copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source) -{ - bool result = false; - - if (source && dest) - { - TextureStorage9_Cube *source9 = TextureStorage9_Cube::makeTextureStorage9_Cube(source->getStorageInstance()); - TextureStorage9_Cube *dest9 = TextureStorage9_Cube::makeTextureStorage9_Cube(dest->getStorageInstance()); - int levels = source9->levelCount(); - for (int f = 0; f < 6; f++) - { - for (int i = 0; i < levels; i++) - { - IDirect3DSurface9 *srcSurf = source9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, false); - IDirect3DSurface9 *dstSurf = dest9->getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + f, i, true); - - result = copyToRenderTarget(dstSurf, srcSurf, source9->isManaged()); - - if (srcSurf) srcSurf->Release(); - if (dstSurf) dstSurf->Release(); - - if (!result) - return false; - } - } - } - - return result; -} - -D3DPOOL Renderer9::getBufferPool(DWORD usage) const -{ - if (mD3d9Ex != NULL) - { - return D3DPOOL_DEFAULT; - } - else - { - if (!(usage & D3DUSAGE_DYNAMIC)) - { - return D3DPOOL_MANAGED; - } - } - - return D3DPOOL_DEFAULT; -} - -bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level) -{ - RECT rect; - rect.left = sourceRect.x; - rect.top = sourceRect.y; - rect.right = sourceRect.x + sourceRect.width; - rect.bottom = sourceRect.y + sourceRect.height; - - return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, level); -} - -bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level) -{ - RECT rect; - rect.left = sourceRect.x; - rect.top = sourceRect.y; - rect.right = sourceRect.x + sourceRect.width; - rect.bottom = sourceRect.y + sourceRect.height; - - return mBlit->copy(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level); -} - -bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect, - bool blitRenderTarget, bool blitDepthStencil) -{ - endScene(); - - if (blitRenderTarget) - { - gl::Renderbuffer *readBuffer = readFramebuffer->getColorbuffer(0); - gl::Renderbuffer *drawBuffer = drawFramebuffer->getColorbuffer(0); - RenderTarget9 *readRenderTarget = NULL; - RenderTarget9 *drawRenderTarget = NULL; - IDirect3DSurface9* readSurface = NULL; - IDirect3DSurface9* drawSurface = NULL; - - if (readBuffer) - { - readRenderTarget = RenderTarget9::makeRenderTarget9(readBuffer->getRenderTarget()); - } - if (drawBuffer) - { - drawRenderTarget = RenderTarget9::makeRenderTarget9(drawBuffer->getRenderTarget()); - } - - if (readRenderTarget) - { - readSurface = readRenderTarget->getSurface(); - } - if (drawRenderTarget) - { - drawSurface = drawRenderTarget->getSurface(); - } - - if (!readSurface || !drawSurface) - { - ERR("Failed to retrieve the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - RECT srcRect; - srcRect.left = readRect.x; - srcRect.right = readRect.x + readRect.width; - srcRect.top = readRect.y; - srcRect.bottom = readRect.y + readRect.height; - - RECT dstRect; - dstRect.left = drawRect.x; - dstRect.right = drawRect.x + drawRect.width; - dstRect.top = drawRect.y; - dstRect.bottom = drawRect.y + drawRect.height; - - HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE); - - readSurface->Release(); - drawSurface->Release(); - - if (FAILED(result)) - { - ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); - return false; - } - } - - if (blitDepthStencil) - { - gl::Renderbuffer *readBuffer = readFramebuffer->getDepthOrStencilbuffer(); - gl::Renderbuffer *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer(); - RenderTarget9 *readDepthStencil = NULL; - RenderTarget9 *drawDepthStencil = NULL; - IDirect3DSurface9* readSurface = NULL; - IDirect3DSurface9* drawSurface = NULL; - - if (readBuffer) - { - readDepthStencil = RenderTarget9::makeRenderTarget9(readBuffer->getDepthStencil()); - } - if (drawBuffer) - { - drawDepthStencil = RenderTarget9::makeRenderTarget9(drawBuffer->getDepthStencil()); - } - - if (readDepthStencil) - { - readSurface = readDepthStencil->getSurface(); - } - if (drawDepthStencil) - { - drawSurface = drawDepthStencil->getSurface(); - } - - if (!readSurface || !drawSurface) - { - ERR("Failed to retrieve the render target."); - return gl::error(GL_OUT_OF_MEMORY, false); - } - - HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE); - - readSurface->Release(); - drawSurface->Release(); - - if (FAILED(result)) - { - ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result); - return false; - } - } - - return true; -} - -void Renderer9::readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) -{ - RenderTarget9 *renderTarget = NULL; - IDirect3DSurface9 *surface = NULL; - gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer(0); - - if (colorbuffer) - { - renderTarget = RenderTarget9::makeRenderTarget9(colorbuffer->getRenderTarget()); - } - - if (renderTarget) - { - surface = renderTarget->getSurface(); - } - - if (!surface) - { - // context must be lost - return; - } - - D3DSURFACE_DESC desc; - surface->GetDesc(&desc); - - if (desc.MultiSampleType != D3DMULTISAMPLE_NONE) - { - UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target - surface->Release(); - return gl::error(GL_OUT_OF_MEMORY); - } - - HRESULT result; - IDirect3DSurface9 *systemSurface = NULL; - bool directToPixels = !packReverseRowOrder && packAlignment <= 4 && getShareHandleSupport() && - x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height && - desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE; - if (directToPixels) - { - // Use the pixels ptr as a shared handle to write directly into client's memory - result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, - D3DPOOL_SYSTEMMEM, &systemSurface, &pixels); - if (FAILED(result)) - { - // Try again without the shared handle - directToPixels = false; - } - } - - if (!directToPixels) - { - result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, - D3DPOOL_SYSTEMMEM, &systemSurface, NULL); - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - surface->Release(); - return gl::error(GL_OUT_OF_MEMORY); - } - } - - result = mDevice->GetRenderTargetData(surface, systemSurface); - surface->Release(); - surface = NULL; - - if (FAILED(result)) - { - systemSurface->Release(); - - // It turns out that D3D will sometimes produce more error - // codes than those documented. - if (d3d9::isDeviceLostError(result)) - { - notifyDeviceLost(); - return gl::error(GL_OUT_OF_MEMORY); - } - else - { - UNREACHABLE(); - return; - } - - } - - if (directToPixels) - { - systemSurface->Release(); - return; - } - - RECT rect; - rect.left = gl::clamp(x, 0L, static_cast(desc.Width)); - rect.top = gl::clamp(y, 0L, static_cast(desc.Height)); - rect.right = gl::clamp(x + width, 0L, static_cast(desc.Width)); - rect.bottom = gl::clamp(y + height, 0L, static_cast(desc.Height)); - - D3DLOCKED_RECT lock; - result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY); - - if (FAILED(result)) - { - UNREACHABLE(); - systemSurface->Release(); - - return; // No sensible error to generate - } - - unsigned char *dest = (unsigned char*)pixels; - unsigned short *dest16 = (unsigned short*)pixels; - - unsigned char *source; - int inputPitch; - if (packReverseRowOrder) - { - source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1); - inputPitch = -lock.Pitch; - } - else - { - source = (unsigned char*)lock.pBits; - inputPitch = lock.Pitch; - } - - unsigned int fastPixelSize = 0; - - if (desc.Format == D3DFMT_A8R8G8B8 && - format == GL_BGRA_EXT && - type == GL_UNSIGNED_BYTE) - { - fastPixelSize = 4; - } - else if ((desc.Format == D3DFMT_A4R4G4B4 && - format == GL_BGRA_EXT && - type == GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT) || - (desc.Format == D3DFMT_A1R5G5B5 && - format == GL_BGRA_EXT && - type == GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT)) - { - fastPixelSize = 2; - } - else if (desc.Format == D3DFMT_A16B16G16R16F && - format == GL_RGBA && - type == GL_HALF_FLOAT_OES) - { - fastPixelSize = 8; - } - else if (desc.Format == D3DFMT_A32B32G32R32F && - format == GL_RGBA && - type == GL_FLOAT) - { - fastPixelSize = 16; - } - - for (int j = 0; j < rect.bottom - rect.top; j++) - { - if (fastPixelSize != 0) - { - // Fast path for formats which require no translation: - // D3DFMT_A8R8G8B8 to BGRA/UNSIGNED_BYTE - // D3DFMT_A4R4G4B4 to BGRA/UNSIGNED_SHORT_4_4_4_4_REV_EXT - // D3DFMT_A1R5G5B5 to BGRA/UNSIGNED_SHORT_1_5_5_5_REV_EXT - // D3DFMT_A16B16G16R16F to RGBA/HALF_FLOAT_OES - // D3DFMT_A32B32G32R32F to RGBA/FLOAT - // - // Note that buffers with no alpha go through the slow path below. - memcpy(dest + j * outputPitch, - source + j * inputPitch, - (rect.right - rect.left) * fastPixelSize); - continue; - } - else if (desc.Format == D3DFMT_A8R8G8B8 && - format == GL_RGBA && - type == GL_UNSIGNED_BYTE) - { - // Fast path for swapping red with blue - for (int i = 0; i < rect.right - rect.left; i++) - { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); - *(unsigned int*)(dest + 4 * i + j * outputPitch) = - (argb & 0xFF00FF00) | // Keep alpha and green - (argb & 0x00FF0000) >> 16 | // Move red to blue - (argb & 0x000000FF) << 16; // Move blue to red - } - continue; - } - - for (int i = 0; i < rect.right - rect.left; i++) - { - float r; - float g; - float b; - float a; - - switch (desc.Format) - { - case D3DFMT_R5G6B5: - { - unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch); - - a = 1.0f; - b = (rgb & 0x001F) * (1.0f / 0x001F); - g = (rgb & 0x07E0) * (1.0f / 0x07E0); - r = (rgb & 0xF800) * (1.0f / 0xF800); - } - break; - case D3DFMT_A1R5G5B5: - { - unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch); - - a = (argb & 0x8000) ? 1.0f : 0.0f; - b = (argb & 0x001F) * (1.0f / 0x001F); - g = (argb & 0x03E0) * (1.0f / 0x03E0); - r = (argb & 0x7C00) * (1.0f / 0x7C00); - } - break; - case D3DFMT_A8R8G8B8: - { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); - - a = (argb & 0xFF000000) * (1.0f / 0xFF000000); - b = (argb & 0x000000FF) * (1.0f / 0x000000FF); - g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00); - r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000); - } - break; - case D3DFMT_X8R8G8B8: - { - unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch); - - a = 1.0f; - b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF); - g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00); - r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000); - } - break; - case D3DFMT_A2R10G10B10: - { - unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch); - - a = (argb & 0xC0000000) * (1.0f / 0xC0000000); - b = (argb & 0x000003FF) * (1.0f / 0x000003FF); - g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00); - r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000); - } - break; - case D3DFMT_A32B32G32R32F: - { - // float formats in D3D are stored rgba, rather than the other way round - r = *((float*)(source + 16 * i + j * inputPitch) + 0); - g = *((float*)(source + 16 * i + j * inputPitch) + 1); - b = *((float*)(source + 16 * i + j * inputPitch) + 2); - a = *((float*)(source + 16 * i + j * inputPitch) + 3); - } - break; - case D3DFMT_A16B16G16R16F: - { - // float formats in D3D are stored rgba, rather than the other way round - r = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 0)); - g = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 1)); - b = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 2)); - a = gl::float16ToFloat32(*((unsigned short*)(source + 8 * i + j * inputPitch) + 3)); - } - break; - default: - UNIMPLEMENTED(); // FIXME - UNREACHABLE(); - return; - } - - switch (format) - { - case GL_RGBA: - switch (type) - { - case GL_UNSIGNED_BYTE: - dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); - dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); - dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); - dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); - break; - default: UNREACHABLE(); - } - break; - case GL_BGRA_EXT: - switch (type) - { - case GL_UNSIGNED_BYTE: - dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f); - dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); - dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f); - dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f); - break; - case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - dest16[i + j * outputPitch / sizeof(unsigned short)] = - ((unsigned short)(15 * a + 0.5f) << 12)| - ((unsigned short)(15 * r + 0.5f) << 8) | - ((unsigned short)(15 * g + 0.5f) << 4) | - ((unsigned short)(15 * b + 0.5f) << 0); - break; - case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: - // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section - // this type is packed as follows: - // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 - // -------------------------------------------------------------------------------- - // | 4th | 3rd | 2nd | 1st component | - // -------------------------------------------------------------------------------- - // in the case of BGRA_EXT, B is the first component, G the second, and so forth. - dest16[i + j * outputPitch / sizeof(unsigned short)] = - ((unsigned short)( a + 0.5f) << 15) | - ((unsigned short)(31 * r + 0.5f) << 10) | - ((unsigned short)(31 * g + 0.5f) << 5) | - ((unsigned short)(31 * b + 0.5f) << 0); - break; - default: UNREACHABLE(); - } - break; - case GL_RGB: - switch (type) - { - case GL_UNSIGNED_SHORT_5_6_5: - dest16[i + j * outputPitch / sizeof(unsigned short)] = - ((unsigned short)(31 * b + 0.5f) << 0) | - ((unsigned short)(63 * g + 0.5f) << 5) | - ((unsigned short)(31 * r + 0.5f) << 11); - break; - case GL_UNSIGNED_BYTE: - dest[3 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f); - dest[3 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f); - dest[3 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f); - break; - default: UNREACHABLE(); - } - break; - default: UNREACHABLE(); - } - } - } - - systemSurface->UnlockRect(); - - systemSurface->Release(); -} - -RenderTarget *Renderer9::createRenderTarget(SwapChain *swapChain, bool depth) -{ - SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); - IDirect3DSurface9 *surface = NULL; - if (depth) - { - surface = swapChain9->getDepthStencil(); - } - else - { - surface = swapChain9->getRenderTarget(); - } - - RenderTarget9 *renderTarget = new RenderTarget9(this, surface); - - return renderTarget; -} - -RenderTarget *Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth) -{ - RenderTarget9 *renderTarget = new RenderTarget9(this, width, height, format, samples); - return renderTarget; -} - -ShaderExecutable *Renderer9::loadExecutable(const void *function, size_t length, rx::ShaderType type) -{ - ShaderExecutable9 *executable = NULL; - - switch (type) - { - case rx::SHADER_VERTEX: - { - IDirect3DVertexShader9 *vshader = createVertexShader((DWORD*)function, length); - if (vshader) - { - executable = new ShaderExecutable9(function, length, vshader); - } - } - break; - case rx::SHADER_PIXEL: - { - IDirect3DPixelShader9 *pshader = createPixelShader((DWORD*)function, length); - if (pshader) - { - executable = new ShaderExecutable9(function, length, pshader); - } - } - break; - default: - UNREACHABLE(); - break; - } - - return executable; -} - -ShaderExecutable *Renderer9::compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround) -{ - const char *profile = NULL; - - switch (type) - { - case rx::SHADER_VERTEX: - profile = getMajorShaderModel() >= 3 ? "vs_3_0" : "vs_2_0"; - break; - case rx::SHADER_PIXEL: - profile = getMajorShaderModel() >= 3 ? "ps_3_0" : "ps_2_0"; - break; - default: - UNREACHABLE(); - return NULL; - } - - // ANGLE issue 486: - // Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization - UINT optimizationFlags = (workaround == ANGLE_D3D_WORKAROUND_SM3_OPTIMIZER ? D3DCOMPILE_SKIP_OPTIMIZATION : ANGLE_COMPILE_OPTIMIZATION_LEVEL); - - ID3DBlob *binary = (ID3DBlob*)compileToBinary(infoLog, shaderHLSL, profile, optimizationFlags, true); - if (!binary) - return NULL; - - ShaderExecutable *executable = loadExecutable(binary->GetBufferPointer(), binary->GetBufferSize(), type); - binary->Release(); - - return executable; -} - -bool Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest) -{ - return mBlit->boxFilter(source, dest); -} - -D3DPOOL Renderer9::getTexturePool(DWORD usage) const -{ - if (mD3d9Ex != NULL) - { - return D3DPOOL_DEFAULT; - } - else - { - if (!(usage & (D3DUSAGE_DEPTHSTENCIL | D3DUSAGE_RENDERTARGET))) - { - return D3DPOOL_MANAGED; - } - } - - return D3DPOOL_DEFAULT; -} - -bool Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged) -{ - if (source && dest) - { - HRESULT result = D3DERR_OUTOFVIDEOMEMORY; - - if (fromManaged) - { - D3DSURFACE_DESC desc; - source->GetDesc(&desc); - - IDirect3DSurface9 *surf = 0; - result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surf, NULL); - - if (SUCCEEDED(result)) - { - Image9::copyLockableSurfaces(surf, source); - result = mDevice->UpdateSurface(surf, NULL, dest, NULL); - surf->Release(); - } - } - else - { - endScene(); - result = mDevice->StretchRect(source, NULL, dest, NULL, D3DTEXF_NONE); - } - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - return false; - } - } - - return true; -} - -Image *Renderer9::createImage() -{ - return new Image9(); -} - -void Renderer9::generateMipmap(Image *dest, Image *src) -{ - Image9 *src9 = Image9::makeImage9(src); - Image9 *dst9 = Image9::makeImage9(dest); - Image9::generateMipmap(dst9, src9); -} - -TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain) -{ - SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain); - return new TextureStorage9_2D(this, swapChain9); -} - -TextureStorage *Renderer9::createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) -{ - return new TextureStorage9_2D(this, levels, internalformat, usage, forceRenderable, width, height); -} - -TextureStorage *Renderer9::createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) -{ - return new TextureStorage9_Cube(this, levels, internalformat, usage, forceRenderable, size); -} - -bool Renderer9::getLUID(LUID *adapterLuid) const -{ - adapterLuid->HighPart = 0; - adapterLuid->LowPart = 0; - - if (mD3d9Ex) - { - mD3d9Ex->GetAdapterLUID(mAdapter, adapterLuid); - return true; - } - - return false; -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h deleted file mode 100644 index 24fd2bdd84..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/Renderer9.h +++ /dev/null @@ -1,356 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// Renderer9.h: Defines a back-end specific class for the D3D9 renderer. - -#ifndef LIBGLESV2_RENDERER_RENDERER9_H_ -#define LIBGLESV2_RENDERER_RENDERER9_H_ - -#include "common/angleutils.h" -#include "libGLESv2/mathutil.h" -#include "libGLESv2/renderer/ShaderCache.h" -#include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h" -#include "libGLESv2/renderer/Renderer.h" -#include "libGLESv2/renderer/RenderTarget.h" - -namespace gl -{ -class Renderbuffer; -} - -namespace rx -{ -class VertexDataManager; -class IndexDataManager; -class StreamingIndexBufferInterface; -struct TranslatedAttribute; - -class Renderer9 : public Renderer -{ - public: - Renderer9(egl::Display *display, HDC hDc, bool softwareDevice); - virtual ~Renderer9(); - - static Renderer9 *makeRenderer9(Renderer *renderer); - - virtual EGLint initialize(); - virtual bool resetDevice(); - - virtual int generateConfigs(ConfigDesc **configDescList); - virtual void deleteConfigs(ConfigDesc *configDescList); - - void startScene(); - void endScene(); - - virtual void sync(bool block); - - virtual SwapChain *createSwapChain(HWND window, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat); - - IDirect3DQuery9* allocateEventQuery(); - void freeEventQuery(IDirect3DQuery9* query); - - // resource creation - IDirect3DVertexShader9 *createVertexShader(const DWORD *function, size_t length); - IDirect3DPixelShader9 *createPixelShader(const DWORD *function, size_t length); - HRESULT createVertexBuffer(UINT Length, DWORD Usage, IDirect3DVertexBuffer9 **ppVertexBuffer); - HRESULT createIndexBuffer(UINT Length, DWORD Usage, D3DFORMAT Format, IDirect3DIndexBuffer9 **ppIndexBuffer); -#if 0 - void *createTexture2D(); - void *createTextureCube(); - void *createQuery(); - void *createIndexBuffer(); - void *createVertexbuffer(); - - // state setup - void applyShaders(); - void applyConstants(); -#endif - virtual void setSamplerState(gl::SamplerType type, int index, const gl::SamplerState &sampler); - virtual void setTexture(gl::SamplerType type, int index, gl::Texture *texture); - - virtual void setRasterizerState(const gl::RasterizerState &rasterState); - virtual void setBlendState(gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::Color &blendColor, - unsigned int sampleMask); - virtual void setDepthStencilState(const gl::DepthStencilState &depthStencilState, int stencilRef, - int stencilBackRef, bool frontFaceCCW); - - virtual void setScissorRectangle(const gl::Rectangle &scissor, bool enabled); - virtual bool setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace, - bool ignoreViewport); - - virtual bool applyRenderTarget(gl::Framebuffer *frameBuffer); - virtual void applyShaders(gl::ProgramBinary *programBinary); - virtual void applyUniforms(gl::ProgramBinary *programBinary, gl::UniformArray *uniformArray); - virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount); - virtual GLenum applyVertexBuffer(gl::ProgramBinary *programBinary, gl::VertexAttribute vertexAttributes[], GLint first, GLsizei count, GLsizei instances); - virtual GLenum applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo); - - virtual void drawArrays(GLenum mode, GLsizei count, GLsizei instances); - virtual void drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances); - - virtual void clear(const gl::ClearParameters &clearParams, gl::Framebuffer *frameBuffer); - - virtual void markAllStateDirty(); - - // lost device - void notifyDeviceLost(); - virtual bool isDeviceLost(); - virtual bool testDeviceLost(bool notify); - virtual bool testDeviceResettable(); - - // Renderer capabilities - IDirect3DDevice9 *getDevice() { return mDevice; } - virtual DWORD getAdapterVendor() const; - virtual std::string getRendererDescription() const; - virtual GUID getAdapterIdentifier() const; - - virtual bool getBGRATextureSupport() const; - virtual bool getDXT1TextureSupport(); - virtual bool getDXT3TextureSupport(); - virtual bool getDXT5TextureSupport(); - virtual bool getEventQuerySupport(); - virtual bool getFloat32TextureSupport(bool *filtering, bool *renderable); - virtual bool getFloat16TextureSupport(bool *filtering, bool *renderable); - virtual bool getLuminanceTextureSupport(); - virtual bool getLuminanceAlphaTextureSupport(); - virtual unsigned int getMaxVertexTextureImageUnits() const; - virtual unsigned int getMaxCombinedTextureImageUnits() const; - virtual unsigned int getReservedVertexUniformVectors() const; - virtual unsigned int getReservedFragmentUniformVectors() const; - virtual unsigned int getMaxVertexUniformVectors() const; - virtual unsigned int getMaxFragmentUniformVectors() const; - virtual unsigned int getMaxVaryingVectors() const; - virtual bool getNonPower2TextureSupport() const; - virtual bool getDepthTextureSupport() const; - virtual bool getOcclusionQuerySupport() const; - virtual bool getInstancingSupport() const; - virtual bool getTextureFilterAnisotropySupport() const; - virtual float getTextureMaxAnisotropy() const; - virtual bool getShareHandleSupport() const; - virtual bool getDerivativeInstructionSupport() const; - virtual bool getPostSubBufferSupport() const; - - virtual int getMajorShaderModel() const; - virtual float getMaxPointSize() const; - virtual int getMaxViewportDimension() const; - virtual int getMaxTextureWidth() const; - virtual int getMaxTextureHeight() const; - virtual bool get32BitIndexSupport() const; - DWORD getCapsDeclTypes() const; - virtual int getMinSwapInterval() const; - virtual int getMaxSwapInterval() const; - - virtual GLsizei getMaxSupportedSamples() const; - int getNearestSupportedSamples(D3DFORMAT format, int requested) const; - - virtual unsigned int getMaxRenderTargets() const; - - D3DFORMAT ConvertTextureInternalFormat(GLint internalformat); - - // Pixel operations - virtual bool copyToRenderTarget(TextureStorageInterface2D *dest, TextureStorageInterface2D *source); - virtual bool copyToRenderTarget(TextureStorageInterfaceCube *dest, TextureStorageInterfaceCube *source); - - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterface2D *storage, GLint level); - virtual bool copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat, - GLint xoffset, GLint yoffset, TextureStorageInterfaceCube *storage, GLenum target, GLint level); - - virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect, - bool blitRenderTarget, bool blitDepthStencil); - virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, - GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels); - - // RenderTarget creation - virtual RenderTarget *createRenderTarget(SwapChain *swapChain, bool depth); - virtual RenderTarget *createRenderTarget(int width, int height, GLenum format, GLsizei samples, bool depth); - - // Shader operations - virtual ShaderExecutable *loadExecutable(const void *function, size_t length, rx::ShaderType type); - virtual ShaderExecutable *compileToExecutable(gl::InfoLog &infoLog, const char *shaderHLSL, rx::ShaderType type, D3DWorkaroundType workaround); - - // Image operations - virtual Image *createImage(); - virtual void generateMipmap(Image *dest, Image *source); - virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain); - virtual TextureStorage *createTextureStorage2D(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); - virtual TextureStorage *createTextureStorageCube(int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); - - // Buffer creation - virtual VertexBuffer *createVertexBuffer(); - virtual IndexBuffer *createIndexBuffer(); - virtual BufferStorage *createBufferStorage(); - - // Query and Fence creation - virtual QueryImpl *createQuery(GLenum type); - virtual FenceImpl *createFence(); - - // D3D9-renderer specific methods - bool boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest); - - D3DPOOL getTexturePool(DWORD usage) const; - - virtual bool getLUID(LUID *adapterLuid) const; - - private: - DISALLOW_COPY_AND_ASSIGN(Renderer9); - - void deinitialize(); - - void applyUniformnfv(gl::Uniform *targetUniform, const GLfloat *v); - void applyUniformniv(gl::Uniform *targetUniform, const GLint *v); - void applyUniformnbv(gl::Uniform *targetUniform, const GLint *v); - - void drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); - void drawIndexedPoints(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer); - - void getMultiSampleSupport(D3DFORMAT format, bool *multiSampleArray); - bool copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged); - gl::Renderbuffer *getNullColorbuffer(gl::Renderbuffer *depthbuffer); - - D3DPOOL getBufferPool(DWORD usage) const; - - HMODULE mD3d9Module; - HDC mDc; - - void initializeDevice(); - D3DPRESENT_PARAMETERS getDefaultPresentParameters(); - void releaseDeviceResources(); - - HRESULT getDeviceStatusCode(); - bool isRemovedDeviceResettable() const; - bool resetRemovedDevice(); - - UINT mAdapter; - D3DDEVTYPE mDeviceType; - bool mSoftwareDevice; // FIXME: Deprecate - IDirect3D9 *mD3d9; // Always valid after successful initialization. - IDirect3D9Ex *mD3d9Ex; // Might be null if D3D9Ex is not supported. - IDirect3DDevice9 *mDevice; - IDirect3DDevice9Ex *mDeviceEx; // Might be null if D3D9Ex is not supported. - - Blit *mBlit; - - HWND mDeviceWindow; - - bool mDeviceLost; - D3DCAPS9 mDeviceCaps; - D3DADAPTER_IDENTIFIER9 mAdapterIdentifier; - - D3DPRIMITIVETYPE mPrimitiveType; - int mPrimitiveCount; - GLsizei mRepeatDraw; - - bool mSceneStarted; - bool mSupportsNonPower2Textures; - bool mSupportsTextureFilterAnisotropy; - int mMinSwapInterval; - int mMaxSwapInterval; - - bool mOcclusionQuerySupport; - bool mEventQuerySupport; - bool mVertexTextureSupport; - - bool mDepthTextureSupport; - - bool mFloat32TextureSupport; - bool mFloat32FilterSupport; - bool mFloat32RenderSupport; - - bool mFloat16TextureSupport; - bool mFloat16FilterSupport; - bool mFloat16RenderSupport; - - bool mDXT1TextureSupport; - bool mDXT3TextureSupport; - bool mDXT5TextureSupport; - - bool mLuminanceTextureSupport; - bool mLuminanceAlphaTextureSupport; - - std::map mMultiSampleSupport; - GLsizei mMaxSupportedSamples; - - // current render target states - unsigned int mAppliedRenderTargetSerial; - unsigned int mAppliedDepthbufferSerial; - unsigned int mAppliedStencilbufferSerial; - bool mDepthStencilInitialized; - bool mRenderTargetDescInitialized; - rx::RenderTarget::Desc mRenderTargetDesc; - unsigned int mCurStencilSize; - unsigned int mCurDepthSize; - - IDirect3DStateBlock9 *mMaskedClearSavedState; - - // previously set render states - bool mForceSetDepthStencilState; - gl::DepthStencilState mCurDepthStencilState; - int mCurStencilRef; - int mCurStencilBackRef; - bool mCurFrontFaceCCW; - - bool mForceSetRasterState; - gl::RasterizerState mCurRasterState; - - bool mForceSetScissor; - gl::Rectangle mCurScissor; - bool mScissorEnabled; - - bool mForceSetViewport; - gl::Rectangle mCurViewport; - float mCurNear; - float mCurFar; - float mCurDepthFront; - - bool mForceSetBlendState; - gl::BlendState mCurBlendState; - gl::Color mCurBlendColor; - GLuint mCurSampleMask; - - // Currently applied sampler states - bool mForceSetVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - gl::SamplerState mCurVertexSamplerStates[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - - bool mForceSetPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; - gl::SamplerState mCurPixelSamplerStates[gl::MAX_TEXTURE_IMAGE_UNITS]; - - // Currently applied textures - unsigned int mCurVertexTextureSerials[gl::IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; - unsigned int mCurPixelTextureSerials[gl::MAX_TEXTURE_IMAGE_UNITS]; - - unsigned int mAppliedIBSerial; - unsigned int mAppliedProgramBinarySerial; - - rx::dx_VertexConstants mVertexConstants; - rx::dx_PixelConstants mPixelConstants; - bool mDxUniformsDirty; - - // A pool of event queries that are currently unused. - std::vector mEventQueryPool; - VertexShaderCache mVertexShaderCache; - PixelShaderCache mPixelShaderCache; - - VertexDataManager *mVertexDataManager; - VertexDeclarationCache mVertexDeclarationCache; - - IndexDataManager *mIndexDataManager; - StreamingIndexBufferInterface *mLineLoopIB; - - enum { NUM_NULL_COLORBUFFER_CACHE_ENTRIES = 12 }; - struct NullColorbufferCacheEntry - { - UINT lruCount; - int width; - int height; - gl::Renderbuffer *buffer; - } mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES]; - UINT mMaxNullColorbufferLRU; - -}; - -} -#endif // LIBGLESV2_RENDERER_RENDERER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp deleted file mode 100644 index 5decf9664d..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader -// executable implementation details. - -#include "libGLESv2/renderer/d3d9/ShaderExecutable9.h" - -#include "common/debug.h" - -namespace rx -{ - -ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable) - : ShaderExecutable(function, length) -{ - mPixelExecutable = executable; - mVertexExecutable = NULL; -} - -ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable) - : ShaderExecutable(function, length) -{ - mVertexExecutable = executable; - mPixelExecutable = NULL; -} - -ShaderExecutable9::~ShaderExecutable9() -{ - if (mVertexExecutable) - { - mVertexExecutable->Release(); - } - if (mPixelExecutable) - { - mPixelExecutable->Release(); - } -} - -ShaderExecutable9 *ShaderExecutable9::makeShaderExecutable9(ShaderExecutable *executable) -{ - ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable9*, executable)); - return static_cast(executable); -} - -IDirect3DVertexShader9 *ShaderExecutable9::getVertexShader() const -{ - return mVertexExecutable; -} - -IDirect3DPixelShader9 *ShaderExecutable9::getPixelShader() const -{ - return mPixelExecutable; -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h deleted file mode 100644 index fa1e6c2844..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/ShaderExecutable9.h +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// ShaderExecutable9.h: Defines a D3D9-specific class to contain shader -// executable implementation details. - -#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ -#define LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ - -#include "libGLESv2/renderer/ShaderExecutable.h" - -namespace rx -{ - -class ShaderExecutable9 : public ShaderExecutable -{ - public: - ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable); - ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable); - virtual ~ShaderExecutable9(); - - static ShaderExecutable9 *makeShaderExecutable9(ShaderExecutable *executable); - - IDirect3DPixelShader9 *getPixelShader() const; - IDirect3DVertexShader9 *getVertexShader() const; - - private: - DISALLOW_COPY_AND_ASSIGN(ShaderExecutable9); - - IDirect3DPixelShader9 *mPixelExecutable; - IDirect3DVertexShader9 *mVertexExecutable; -}; - -} - -#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_ \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp deleted file mode 100644 index dd8895d18d..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.cpp +++ /dev/null @@ -1,445 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain. - -#include "libGLESv2/renderer/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" - -namespace rx -{ - -SwapChain9::SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat) - : mRenderer(renderer), SwapChain(window, shareHandle, backBufferFormat, depthBufferFormat) -{ - mSwapChain = NULL; - mBackBuffer = NULL; - mDepthStencil = NULL; - mRenderTarget = NULL; - mOffscreenTexture = NULL; - mWidth = -1; - mHeight = -1; - mSwapInterval = -1; -} - -SwapChain9::~SwapChain9() -{ - release(); -} - -void SwapChain9::release() -{ - if (mSwapChain) - { - mSwapChain->Release(); - mSwapChain = NULL; - } - - if (mBackBuffer) - { - mBackBuffer->Release(); - mBackBuffer = NULL; - } - - if (mDepthStencil) - { - mDepthStencil->Release(); - mDepthStencil = NULL; - } - - if (mRenderTarget) - { - mRenderTarget->Release(); - mRenderTarget = NULL; - } - - if (mOffscreenTexture) - { - mOffscreenTexture->Release(); - mOffscreenTexture = NULL; - } - - if (mWindow) - mShareHandle = NULL; -} - -static DWORD convertInterval(EGLint interval) -{ -#if ANGLE_FORCE_VSYNC_OFF - return D3DPRESENT_INTERVAL_IMMEDIATE; -#else - switch(interval) - { - case 0: return D3DPRESENT_INTERVAL_IMMEDIATE; - case 1: return D3DPRESENT_INTERVAL_ONE; - case 2: return D3DPRESENT_INTERVAL_TWO; - case 3: return D3DPRESENT_INTERVAL_THREE; - case 4: return D3DPRESENT_INTERVAL_FOUR; - default: UNREACHABLE(); - } - - return D3DPRESENT_INTERVAL_DEFAULT; -#endif -} - -EGLint SwapChain9::resize(int backbufferWidth, int backbufferHeight) -{ - // D3D9 does not support resizing swap chains without recreating them - return reset(backbufferWidth, backbufferHeight, mSwapInterval); -} - -EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval) -{ - IDirect3DDevice9 *device = mRenderer->getDevice(); - - if (device == NULL) - { - return EGL_BAD_ACCESS; - } - - // Evict all non-render target textures to system memory and release all resources - // before reallocating them to free up as much video memory as possible. - device->EvictManagedResources(); - - HRESULT result; - - // Release specific resources to free up memory for the new render target, while the - // old render target still exists for the purpose of preserving its contents. - if (mSwapChain) - { - mSwapChain->Release(); - mSwapChain = NULL; - } - - if (mBackBuffer) - { - mBackBuffer->Release(); - mBackBuffer = NULL; - } - - if (mOffscreenTexture) - { - mOffscreenTexture->Release(); - mOffscreenTexture = NULL; - } - - if (mDepthStencil) - { - mDepthStencil->Release(); - mDepthStencil = NULL; - } - - HANDLE *pShareHandle = NULL; - if (!mWindow && mRenderer->getShareHandleSupport()) - { - pShareHandle = &mShareHandle; - } - - result = device->CreateTexture(backbufferWidth, backbufferHeight, 1, D3DUSAGE_RENDERTARGET, - gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat), D3DPOOL_DEFAULT, - &mOffscreenTexture, pShareHandle); - if (FAILED(result)) - { - ERR("Could not create offscreen texture: %08lX", result); - release(); - - if (d3d9::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } - } - - IDirect3DSurface9 *oldRenderTarget = mRenderTarget; - - result = mOffscreenTexture->GetSurfaceLevel(0, &mRenderTarget); - ASSERT(SUCCEEDED(result)); - - if (oldRenderTarget) - { - RECT rect = - { - 0, 0, - mWidth, mHeight - }; - - if (rect.right > static_cast(backbufferWidth)) - { - rect.right = backbufferWidth; - } - - if (rect.bottom > static_cast(backbufferHeight)) - { - rect.bottom = backbufferHeight; - } - - mRenderer->endScene(); - - result = device->StretchRect(oldRenderTarget, &rect, mRenderTarget, &rect, D3DTEXF_NONE); - ASSERT(SUCCEEDED(result)); - - oldRenderTarget->Release(); - } - - if (mWindow) - { - D3DPRESENT_PARAMETERS presentParameters = {0}; - presentParameters.AutoDepthStencilFormat = gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat); - presentParameters.BackBufferCount = 1; - presentParameters.BackBufferFormat = gl_d3d9::ConvertRenderbufferFormat(mBackBufferFormat); - presentParameters.EnableAutoDepthStencil = FALSE; - presentParameters.Flags = 0; - presentParameters.hDeviceWindow = mWindow; - presentParameters.MultiSampleQuality = 0; // FIXME: Unimplemented - presentParameters.MultiSampleType = D3DMULTISAMPLE_NONE; // FIXME: Unimplemented - presentParameters.PresentationInterval = convertInterval(swapInterval); - presentParameters.SwapEffect = D3DSWAPEFFECT_DISCARD; - presentParameters.Windowed = TRUE; - presentParameters.BackBufferWidth = backbufferWidth; - presentParameters.BackBufferHeight = backbufferHeight; - - // http://crbug.com/140239 - // http://crbug.com/143434 - // - // Some AMD/Intel switchable systems / drivers appear to round swap chain surfaces to a multiple of 64 pixels in width - // when using the integrated Intel. This rounds the width up rather than down. - // - // Some non-switchable AMD GPUs / drivers do not respect the source rectangle to Present. Therefore, when the vendor ID - // is not Intel, the back buffer width must be exactly the same width as the window or horizontal scaling will occur. - if (mRenderer->getAdapterVendor() == VENDOR_ID_INTEL) - { - presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64; - } - - result = device->CreateAdditionalSwapChain(&presentParameters, &mSwapChain); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL || result == D3DERR_DEVICELOST); - - ERR("Could not create additional swap chains or offscreen surfaces: %08lX", result); - release(); - - if (d3d9::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } - } - - result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); - ASSERT(SUCCEEDED(result)); - InvalidateRect(mWindow, NULL, FALSE); - } - - if (mDepthBufferFormat != GL_NONE) - { - result = device->CreateDepthStencilSurface(backbufferWidth, backbufferHeight, - gl_d3d9::ConvertRenderbufferFormat(mDepthBufferFormat), - D3DMULTISAMPLE_NONE, 0, FALSE, &mDepthStencil, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_INVALIDCALL); - - ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result); - release(); - - if (d3d9::isDeviceLostError(result)) - { - return EGL_CONTEXT_LOST; - } - else - { - return EGL_BAD_ALLOC; - } - } - } - - mWidth = backbufferWidth; - mHeight = backbufferHeight; - mSwapInterval = swapInterval; - - return EGL_SUCCESS; -} - -// parameters should be validated/clamped by caller -EGLint SwapChain9::swapRect(EGLint x, EGLint y, EGLint width, EGLint height) -{ - if (!mSwapChain) - { - return EGL_SUCCESS; - } - - IDirect3DDevice9 *device = mRenderer->getDevice(); - - // Disable all pipeline operations - device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); - device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID); - device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); - device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); - device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); - device->SetRenderState(D3DRS_STENCILENABLE, FALSE); - device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0); - device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA | D3DCOLORWRITEENABLE_BLUE | D3DCOLORWRITEENABLE_GREEN | D3DCOLORWRITEENABLE_RED); - device->SetRenderState(D3DRS_SRGBWRITEENABLE, FALSE); - device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE); - device->SetPixelShader(NULL); - device->SetVertexShader(NULL); - - device->SetRenderTarget(0, mBackBuffer); - device->SetDepthStencilSurface(NULL); - - device->SetTexture(0, mOffscreenTexture); - device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1); - device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); - device->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); - device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT); - device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); - device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); - device->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); - - for (UINT streamIndex = 0; streamIndex < gl::MAX_VERTEX_ATTRIBS; streamIndex++) - { - device->SetStreamSourceFreq(streamIndex, 1); - } - - D3DVIEWPORT9 viewport = {0, 0, mWidth, mHeight, 0.0f, 1.0f}; - device->SetViewport(&viewport); - - float x1 = x - 0.5f; - float y1 = (mHeight - y - height) - 0.5f; - float x2 = (x + width) - 0.5f; - float y2 = (mHeight - y) - 0.5f; - - float u1 = x / float(mWidth); - float v1 = y / float(mHeight); - float u2 = (x + width) / float(mWidth); - float v2 = (y + height) / float(mHeight); - - float quad[4][6] = {{x1, y1, 0.0f, 1.0f, u1, v2}, - {x2, y1, 0.0f, 1.0f, u2, v2}, - {x2, y2, 0.0f, 1.0f, u2, v1}, - {x1, y2, 0.0f, 1.0f, u1, v1}}; // x, y, z, rhw, u, v - - mRenderer->startScene(); - device->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, quad, 6 * sizeof(float)); - mRenderer->endScene(); - - device->SetTexture(0, NULL); - - RECT rect = - { - x, mHeight - y - height, - x + width, mHeight - y - }; - - HRESULT result = mSwapChain->Present(&rect, &rect, NULL, NULL, 0); - - mRenderer->markAllStateDirty(); - - if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DRIVERINTERNALERROR) - { - return EGL_BAD_ALLOC; - } - - // http://crbug.com/313210 - // If our swap failed, trigger a device lost event. Resetting will work around an AMD-specific - // device removed bug with lost contexts when reinstalling drivers. - if (FAILED(result)) - { - mRenderer->notifyDeviceLost(); - return EGL_CONTEXT_LOST; - } - - return EGL_SUCCESS; -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *SwapChain9::getRenderTarget() -{ - if (mRenderTarget) - { - mRenderTarget->AddRef(); - } - - return mRenderTarget; -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *SwapChain9::getDepthStencil() -{ - if (mDepthStencil) - { - mDepthStencil->AddRef(); - } - - return mDepthStencil; -} - -// Increments refcount on texture. -// caller must Release() the returned texture -IDirect3DTexture9 *SwapChain9::getOffscreenTexture() -{ - if (mOffscreenTexture) - { - mOffscreenTexture->AddRef(); - } - - return mOffscreenTexture; -} - -SwapChain9 *SwapChain9::makeSwapChain9(SwapChain *swapChain) -{ - ASSERT(HAS_DYNAMIC_TYPE(rx::SwapChain9*, swapChain)); - return static_cast(swapChain); -} - -void SwapChain9::recreate() -{ - if (!mSwapChain) - { - return; - } - - IDirect3DDevice9 *device = mRenderer->getDevice(); - if (device == NULL) - { - return; - } - - D3DPRESENT_PARAMETERS presentParameters; - HRESULT result = mSwapChain->GetPresentParameters(&presentParameters); - ASSERT(SUCCEEDED(result)); - - IDirect3DSwapChain9* newSwapChain = NULL; - result = device->CreateAdditionalSwapChain(&presentParameters, &newSwapChain); - if (FAILED(result)) - { - return; - } - - mSwapChain->Release(); - mSwapChain = newSwapChain; - - mBackBuffer->Release(); - result = mSwapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &mBackBuffer); - ASSERT(SUCCEEDED(result)); -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h deleted file mode 100644 index 16a62bd86f..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/SwapChain9.h +++ /dev/null @@ -1,55 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// SwapChain9.h: Defines a back-end specific class for the D3D9 swap chain. - -#ifndef LIBGLESV2_RENDERER_SWAPCHAIN9_H_ -#define LIBGLESV2_RENDERER_SWAPCHAIN9_H_ - -#include "common/angleutils.h" -#include "libGLESv2/renderer/SwapChain.h" - -namespace rx -{ -class Renderer9; - -class SwapChain9 : public SwapChain -{ - public: - SwapChain9(Renderer9 *renderer, HWND window, HANDLE shareHandle, - GLenum backBufferFormat, GLenum depthBufferFormat); - virtual ~SwapChain9(); - - EGLint resize(EGLint backbufferWidth, EGLint backbufferHeight); - virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval); - virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height); - virtual void recreate(); - - virtual IDirect3DSurface9 *getRenderTarget(); - virtual IDirect3DSurface9 *getDepthStencil(); - virtual IDirect3DTexture9 *getOffscreenTexture(); - - static SwapChain9 *makeSwapChain9(SwapChain *swapChain); - - private: - DISALLOW_COPY_AND_ASSIGN(SwapChain9); - - void release(); - - Renderer9 *mRenderer; - EGLint mHeight; - EGLint mWidth; - EGLint mSwapInterval; - - IDirect3DSwapChain9 *mSwapChain; - IDirect3DSurface9 *mBackBuffer; - IDirect3DSurface9 *mRenderTarget; - IDirect3DSurface9 *mDepthStencil; - IDirect3DTexture9* mOffscreenTexture; -}; - -} -#endif // LIBGLESV2_RENDERER_SWAPCHAIN9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp deleted file mode 100644 index 2486a9a5bf..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.cpp +++ /dev/null @@ -1,328 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TextureStorage9.cpp: Implements the abstract rx::TextureStorage9 class and its concrete derived -// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the -// D3D9 texture. - -#include "libGLESv2/main.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" -#include "libGLESv2/renderer/d3d9/TextureStorage9.h" -#include "libGLESv2/renderer/d3d9/SwapChain9.h" -#include "libGLESv2/renderer/d3d9/RenderTarget9.h" -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/Texture.h" - -namespace rx -{ -TextureStorage9::TextureStorage9(Renderer *renderer, DWORD usage) - : mLodOffset(0), - mRenderer(Renderer9::makeRenderer9(renderer)), - mD3DUsage(usage), - mD3DPool(mRenderer->getTexturePool(usage)) -{ -} - -TextureStorage9::~TextureStorage9() -{ -} - -TextureStorage9 *TextureStorage9::makeTextureStorage9(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9*, storage)); - return static_cast(storage); -} - -DWORD TextureStorage9::GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable) -{ - DWORD d3dusage = 0; - - if (d3dfmt == D3DFMT_INTZ) - { - d3dusage |= D3DUSAGE_DEPTHSTENCIL; - } - else if(forceRenderable || (TextureStorage9::IsTextureFormatRenderable(d3dfmt) && (glusage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE))) - { - d3dusage |= D3DUSAGE_RENDERTARGET; - } - return d3dusage; -} - -bool TextureStorage9::IsTextureFormatRenderable(D3DFORMAT format) -{ - if (format == D3DFMT_INTZ) - { - return true; - } - switch(format) - { - case D3DFMT_L8: - case D3DFMT_A8L8: - case D3DFMT_DXT1: - case D3DFMT_DXT3: - case D3DFMT_DXT5: - return false; - case D3DFMT_A8R8G8B8: - case D3DFMT_X8R8G8B8: - case D3DFMT_A16B16G16R16F: - case D3DFMT_A32B32G32R32F: - return true; - default: - UNREACHABLE(); - } - - return false; -} - -bool TextureStorage9::isRenderTarget() const -{ - return (mD3DUsage & (D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) != 0; -} - -bool TextureStorage9::isManaged() const -{ - return (mD3DPool == D3DPOOL_MANAGED); -} - -D3DPOOL TextureStorage9::getPool() const -{ - return mD3DPool; -} - -DWORD TextureStorage9::getUsage() const -{ - return mD3DUsage; -} - -int TextureStorage9::getLodOffset() const -{ - return mLodOffset; -} - -int TextureStorage9::levelCount() -{ - return getBaseTexture() ? getBaseTexture()->GetLevelCount() - getLodOffset() : 0; -} - -TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain) : TextureStorage9(renderer, D3DUSAGE_RENDERTARGET) -{ - IDirect3DTexture9 *surfaceTexture = swapchain->getOffscreenTexture(); - mTexture = surfaceTexture; - mRenderTarget = NULL; - - initializeRenderTarget(); -} - -TextureStorage9_2D::TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height) - : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable)) -{ - mTexture = NULL; - mRenderTarget = NULL; - // if the width or height is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (width > 0 && height > 0) - { - IDirect3DDevice9 *device = mRenderer->getDevice(); - gl::MakeValidSize(false, gl::IsCompressed(internalformat), &width, &height, &mLodOffset); - HRESULT result = device->CreateTexture(width, height, levels ? levels + mLodOffset : 0, getUsage(), - mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - gl::error(GL_OUT_OF_MEMORY); - } - } - - initializeRenderTarget(); -} - -TextureStorage9_2D::~TextureStorage9_2D() -{ - if (mTexture) - { - mTexture->Release(); - } - - delete mRenderTarget; -} - -TextureStorage9_2D *TextureStorage9_2D::makeTextureStorage9_2D(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_2D*, storage)); - return static_cast(storage); -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *TextureStorage9_2D::getSurfaceLevel(int level, bool dirty) -{ - IDirect3DSurface9 *surface = NULL; - - if (mTexture) - { - HRESULT result = mTexture->GetSurfaceLevel(level + mLodOffset, &surface); - ASSERT(SUCCEEDED(result)); - - // With managed textures the driver needs to be informed of updates to the lower mipmap levels - if (level + mLodOffset != 0 && isManaged() && dirty) - { - mTexture->AddDirtyRect(NULL); - } - } - - return surface; -} - -RenderTarget *TextureStorage9_2D::getRenderTarget() -{ - return mRenderTarget; -} - -void TextureStorage9_2D::generateMipmap(int level) -{ - IDirect3DSurface9 *upper = getSurfaceLevel(level - 1, false); - IDirect3DSurface9 *lower = getSurfaceLevel(level, true); - - if (upper != NULL && lower != NULL) - { - mRenderer->boxFilter(upper, lower); - } - - if (upper != NULL) upper->Release(); - if (lower != NULL) lower->Release(); -} - -IDirect3DBaseTexture9 *TextureStorage9_2D::getBaseTexture() const -{ - return mTexture; -} - -void TextureStorage9_2D::initializeRenderTarget() -{ - ASSERT(mRenderTarget == NULL); - - if (mTexture != NULL && isRenderTarget()) - { - IDirect3DSurface9 *surface = getSurfaceLevel(0, false); - - mRenderTarget = new RenderTarget9(mRenderer, surface); - } -} - -TextureStorage9_Cube::TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size) - : TextureStorage9(renderer, GetTextureUsage(Renderer9::makeRenderer9(renderer)->ConvertTextureInternalFormat(internalformat), usage, forceRenderable)) -{ - mTexture = NULL; - for (int i = 0; i < 6; ++i) - { - mRenderTarget[i] = NULL; - } - - // if the size is not positive this should be treated as an incomplete texture - // we handle that here by skipping the d3d texture creation - if (size > 0) - { - IDirect3DDevice9 *device = mRenderer->getDevice(); - int height = size; - gl::MakeValidSize(false, gl::IsCompressed(internalformat), &size, &height, &mLodOffset); - HRESULT result = device->CreateCubeTexture(size, levels ? levels + mLodOffset : 0, getUsage(), - mRenderer->ConvertTextureInternalFormat(internalformat), getPool(), &mTexture, NULL); - - if (FAILED(result)) - { - ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY); - gl::error(GL_OUT_OF_MEMORY); - } - } - - initializeRenderTarget(); -} - -TextureStorage9_Cube::~TextureStorage9_Cube() -{ - if (mTexture) - { - mTexture->Release(); - } - - for (int i = 0; i < 6; ++i) - { - delete mRenderTarget[i]; - } -} - -TextureStorage9_Cube *TextureStorage9_Cube::makeTextureStorage9_Cube(TextureStorage *storage) -{ - ASSERT(HAS_DYNAMIC_TYPE(TextureStorage9_Cube*, storage)); - return static_cast(storage); -} - -// Increments refcount on surface. -// caller must Release() the returned surface -IDirect3DSurface9 *TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level, bool dirty) -{ - IDirect3DSurface9 *surface = NULL; - - if (mTexture) - { - D3DCUBEMAP_FACES face = gl_d3d9::ConvertCubeFace(faceTarget); - HRESULT result = mTexture->GetCubeMapSurface(face, level + mLodOffset, &surface); - ASSERT(SUCCEEDED(result)); - - // With managed textures the driver needs to be informed of updates to the lower mipmap levels - if (level != 0 && isManaged() && dirty) - { - mTexture->AddDirtyRect(face, NULL); - } - } - - return surface; -} - -RenderTarget *TextureStorage9_Cube::getRenderTarget(GLenum faceTarget) -{ - return mRenderTarget[gl::TextureCubeMap::faceIndex(faceTarget)]; -} - -void TextureStorage9_Cube::generateMipmap(int face, int level) -{ - IDirect3DSurface9 *upper = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level - 1, false); - IDirect3DSurface9 *lower = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + face, level, true); - - if (upper != NULL && lower != NULL) - { - mRenderer->boxFilter(upper, lower); - } - - if (upper != NULL) upper->Release(); - if (lower != NULL) lower->Release(); -} - -IDirect3DBaseTexture9 *TextureStorage9_Cube::getBaseTexture() const -{ - return mTexture; -} - -void TextureStorage9_Cube::initializeRenderTarget() -{ - if (mTexture != NULL && isRenderTarget()) - { - IDirect3DSurface9 *surface = NULL; - - for (int i = 0; i < 6; ++i) - { - ASSERT(mRenderTarget[i] == NULL); - - surface = getCubeMapSurface(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, false); - - mRenderTarget[i] = new RenderTarget9(mRenderer, surface); - } - } -} - -} \ No newline at end of file diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h deleted file mode 100644 index 86f551a131..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/TextureStorage9.h +++ /dev/null @@ -1,109 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// TextureStorage9.h: Defines the abstract rx::TextureStorage9 class and its concrete derived -// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the -// D3D9 texture. - -#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ -#define LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ - -#include "libGLESv2/renderer/TextureStorage.h" -#include "common/debug.h" - -namespace rx -{ -class Renderer9; -class SwapChain9; -class RenderTarget; -class RenderTarget9; -class Blit; - -class TextureStorage9 : public TextureStorage -{ - public: - TextureStorage9(Renderer *renderer, DWORD usage); - virtual ~TextureStorage9(); - - static TextureStorage9 *makeTextureStorage9(TextureStorage *storage); - - static DWORD GetTextureUsage(D3DFORMAT d3dfmt, GLenum glusage, bool forceRenderable); - static bool IsTextureFormatRenderable(D3DFORMAT format); - - D3DPOOL getPool() const; - DWORD getUsage() const; - - virtual IDirect3DBaseTexture9 *getBaseTexture() const = 0; - virtual RenderTarget *getRenderTarget() { return NULL; } - virtual RenderTarget *getRenderTarget(GLenum faceTarget) { return NULL; } - virtual void generateMipmap(int level) {}; - virtual void generateMipmap(int face, int level) {}; - - virtual int getLodOffset() const; - virtual bool isRenderTarget() const; - virtual bool isManaged() const; - virtual int levelCount(); - - protected: - int mLodOffset; - Renderer9 *mRenderer; - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage9); - - const DWORD mD3DUsage; - const D3DPOOL mD3DPool; -}; - -class TextureStorage9_2D : public TextureStorage9 -{ - public: - TextureStorage9_2D(Renderer *renderer, SwapChain9 *swapchain); - TextureStorage9_2D(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, GLsizei width, GLsizei height); - virtual ~TextureStorage9_2D(); - - static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage); - - IDirect3DSurface9 *getSurfaceLevel(int level, bool dirty); - virtual RenderTarget *getRenderTarget(); - virtual IDirect3DBaseTexture9 *getBaseTexture() const; - virtual void generateMipmap(int level); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage9_2D); - - void initializeRenderTarget(); - - IDirect3DTexture9 *mTexture; - RenderTarget9 *mRenderTarget; -}; - -class TextureStorage9_Cube : public TextureStorage9 -{ - public: - TextureStorage9_Cube(Renderer *renderer, int levels, GLenum internalformat, GLenum usage, bool forceRenderable, int size); - virtual ~TextureStorage9_Cube(); - - static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage); - - IDirect3DSurface9 *getCubeMapSurface(GLenum faceTarget, int level, bool dirty); - virtual RenderTarget *getRenderTarget(GLenum faceTarget); - virtual IDirect3DBaseTexture9 *getBaseTexture() const; - virtual void generateMipmap(int face, int level); - - private: - DISALLOW_COPY_AND_ASSIGN(TextureStorage9_Cube); - - void initializeRenderTarget(); - - IDirect3DCubeTexture9 *mTexture; - RenderTarget9 *mRenderTarget[6]; -}; - -} - -#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_ - diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp deleted file mode 100644 index 57f5bcd256..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.cpp +++ /dev/null @@ -1,530 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation. - -#include "libGLESv2/renderer/d3d9/VertexBuffer9.h" -#include "libGLESv2/renderer/d3d9/vertexconversion.h" -#include "libGLESv2/renderer/BufferStorage.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/renderer/d3d9/Renderer9.h" - -#include "libGLESv2/Buffer.h" - -namespace rx -{ - -bool VertexBuffer9::mTranslationsInitialized = false; -VertexBuffer9::FormatConverter VertexBuffer9::mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; - -VertexBuffer9::VertexBuffer9(rx::Renderer9 *const renderer) : mRenderer(renderer) -{ - mVertexBuffer = NULL; - mBufferSize = 0; - mDynamicUsage = false; - - if (!mTranslationsInitialized) - { - initializeTranslations(renderer->getCapsDeclTypes()); - mTranslationsInitialized = true; - } -} - -VertexBuffer9::~VertexBuffer9() -{ - if (mVertexBuffer) - { - mVertexBuffer->Release(); - mVertexBuffer = NULL; - } -} - -bool VertexBuffer9::initialize(unsigned int size, bool dynamicUsage) -{ - if (mVertexBuffer) - { - mVertexBuffer->Release(); - mVertexBuffer = NULL; - } - - updateSerial(); - - if (size > 0) - { - DWORD flags = D3DUSAGE_WRITEONLY; - if (dynamicUsage) - { - flags |= D3DUSAGE_DYNAMIC; - } - - HRESULT result = mRenderer->createVertexBuffer(size, flags, &mVertexBuffer); - - if (FAILED(result)) - { - ERR("Out of memory allocating a vertex buffer of size %lu.", size); - return false; - } - } - - mBufferSize = size; - mDynamicUsage = dynamicUsage; - return true; -} - -VertexBuffer9 *VertexBuffer9::makeVertexBuffer9(VertexBuffer *vertexBuffer) -{ - ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer9*, vertexBuffer)); - return static_cast(vertexBuffer); -} - -bool VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, - GLsizei instances, unsigned int offset) -{ - if (mVertexBuffer) - { - gl::Buffer *buffer = attrib.mBoundBuffer.get(); - - int inputStride = attrib.stride(); - int elementSize = attrib.typeSize(); - const FormatConverter &converter = formatConverter(attrib); - - DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; - - void *mapPtr = NULL; - - unsigned int mapSize; - if (!spaceRequired(attrib, count, instances, &mapSize)) - { - return false; - } - - HRESULT result = mVertexBuffer->Lock(offset, mapSize, &mapPtr, lockFlags); - - if (FAILED(result)) - { - ERR("Lock failed with error 0x%08x", result); - return false; - } - - const char *input = NULL; - if (buffer) - { - BufferStorage *storage = buffer->getStorage(); - input = static_cast(storage->getData()) + static_cast(attrib.mOffset); - } - else - { - input = static_cast(attrib.mPointer); - } - - if (instances == 0 || attrib.mDivisor == 0) - { - input += inputStride * start; - } - - if (converter.identity && inputStride == elementSize) - { - memcpy(mapPtr, input, count * inputStride); - } - else - { - converter.convertArray(input, inputStride, count, mapPtr); - } - - mVertexBuffer->Unlock(); - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -bool VertexBuffer9::storeRawData(const void* data, unsigned int size, unsigned int offset) -{ - if (mVertexBuffer) - { - DWORD lockFlags = mDynamicUsage ? D3DLOCK_NOOVERWRITE : 0; - - void *mapPtr = NULL; - HRESULT result = mVertexBuffer->Lock(offset, size, &mapPtr, lockFlags); - - if (FAILED(result)) - { - ERR("Lock failed with error 0x%08x", result); - return false; - } - - memcpy(mapPtr, data, size); - - mVertexBuffer->Unlock(); - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -bool VertexBuffer9::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, - unsigned int *outSpaceRequired) const -{ - return spaceRequired(attrib, count, instances, outSpaceRequired); -} - -bool VertexBuffer9::requiresConversion(const gl::VertexAttribute &attrib) const -{ - return !formatConverter(attrib).identity; -} - -unsigned int VertexBuffer9::getVertexSize(const gl::VertexAttribute &attrib) const -{ - unsigned int spaceRequired; - return getSpaceRequired(attrib, 1, 0, &spaceRequired) ? spaceRequired : 0; -} - -D3DDECLTYPE VertexBuffer9::getDeclType(const gl::VertexAttribute &attrib) const -{ - return formatConverter(attrib).d3dDeclType; -} - -unsigned int VertexBuffer9::getBufferSize() const -{ - return mBufferSize; -} - -bool VertexBuffer9::setBufferSize(unsigned int size) -{ - if (size > mBufferSize) - { - return initialize(size, mDynamicUsage); - } - else - { - return true; - } -} - -bool VertexBuffer9::discard() -{ - if (mVertexBuffer) - { - void *dummy; - HRESULT result; - - result = mVertexBuffer->Lock(0, 1, &dummy, D3DLOCK_DISCARD); - if (FAILED(result)) - { - ERR("Discard lock failed with error 0x%08x", result); - return false; - } - - result = mVertexBuffer->Unlock(); - if (FAILED(result)) - { - ERR("Discard unlock failed with error 0x%08x", result); - return false; - } - - return true; - } - else - { - ERR("Vertex buffer not initialized."); - return false; - } -} - -IDirect3DVertexBuffer9 * VertexBuffer9::getBuffer() const -{ - return mVertexBuffer; -} - -// Mapping from OpenGL-ES vertex attrib type to D3D decl type: -// -// BYTE SHORT (Cast) -// BYTE-norm FLOAT (Normalize) (can't be exactly represented as SHORT-norm) -// UNSIGNED_BYTE UBYTE4 (Identity) or SHORT (Cast) -// UNSIGNED_BYTE-norm UBYTE4N (Identity) or FLOAT (Normalize) -// SHORT SHORT (Identity) -// SHORT-norm SHORT-norm (Identity) or FLOAT (Normalize) -// UNSIGNED_SHORT FLOAT (Cast) -// UNSIGNED_SHORT-norm USHORT-norm (Identity) or FLOAT (Normalize) -// FIXED (not in WebGL) FLOAT (FixedToFloat) -// FLOAT FLOAT (Identity) - -// GLToCType maps from GL type (as GLenum) to the C typedef. -template struct GLToCType { }; - -template <> struct GLToCType { typedef GLbyte type; }; -template <> struct GLToCType { typedef GLubyte type; }; -template <> struct GLToCType { typedef GLshort type; }; -template <> struct GLToCType { typedef GLushort type; }; -template <> struct GLToCType { typedef GLuint type; }; -template <> struct GLToCType { typedef GLfloat type; }; - -// This differs from D3DDECLTYPE in that it is unsized. (Size expansion is applied last.) -enum D3DVertexType -{ - D3DVT_FLOAT, - D3DVT_SHORT, - D3DVT_SHORT_NORM, - D3DVT_UBYTE, - D3DVT_UBYTE_NORM, - D3DVT_USHORT_NORM -}; - -// D3DToCType maps from D3D vertex type (as enum D3DVertexType) to the corresponding C type. -template struct D3DToCType { }; - -template <> struct D3DToCType { typedef float type; }; -template <> struct D3DToCType { typedef short type; }; -template <> struct D3DToCType { typedef short type; }; -template <> struct D3DToCType { typedef unsigned char type; }; -template <> struct D3DToCType { typedef unsigned char type; }; -template <> struct D3DToCType { typedef unsigned short type; }; - -// Encode the type/size combinations that D3D permits. For each type/size it expands to a widener that will provide the appropriate final size. -template struct WidenRule { }; - -template struct WidenRule : NoWiden { }; -template struct WidenRule : WidenToEven { }; -template struct WidenRule : WidenToEven { }; -template struct WidenRule : WidenToFour { }; -template struct WidenRule : WidenToFour { }; -template struct WidenRule : WidenToEven { }; - -// VertexTypeFlags encodes the D3DCAPS9::DeclType flag and vertex declaration flag for each D3D vertex type & size combination. -template struct VertexTypeFlags { }; - -template -struct VertexTypeFlagsHelper -{ - enum { capflag = _capflag }; - enum { declflag = _declflag }; -}; - -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT1> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT2> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT3> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_FLOAT4> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT2> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper<0, D3DDECLTYPE_SHORT4> { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; -template <> struct VertexTypeFlags : VertexTypeFlagsHelper { }; - - -// VertexTypeMapping maps GL type & normalized flag to preferred and fallback D3D vertex types (as D3DVertexType enums). -template struct VertexTypeMapping { }; - -template -struct VertexTypeMappingBase -{ - enum { preferred = Preferred }; - enum { fallback = Fallback }; -}; - -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Normalize -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity, Cast -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity, Normalize -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast, Normalize -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast -template <> struct VertexTypeMapping : VertexTypeMappingBase { }; // Cast, Normalize -template struct VertexTypeMapping : VertexTypeMappingBase { }; // FixedToFloat -template struct VertexTypeMapping : VertexTypeMappingBase { }; // Identity - - -// Given a GL type & norm flag and a D3D type, ConversionRule provides the type conversion rule (Cast, Normalize, Identity, FixedToFloat). -// The conversion rules themselves are defined in vertexconversion.h. - -// Almost all cases are covered by Cast (including those that are actually Identity since Cast knows it's an identity mapping). -template -struct ConversionRule : Cast::type, typename D3DToCType::type> { }; - -// All conversions from normalized types to float use the Normalize operator. -template struct ConversionRule : Normalize::type> { }; - -// Use a full specialization for this so that it preferentially matches ahead of the generic normalize-to-float rules. -template <> struct ConversionRule : FixedToFloat { }; -template <> struct ConversionRule : FixedToFloat { }; - -// A 2-stage construction is used for DefaultVertexValues because float must use SimpleDefaultValues (i.e. 0/1) -// whether it is normalized or not. -template struct DefaultVertexValuesStage2 { }; - -template struct DefaultVertexValuesStage2 : NormalizedDefaultValues { }; -template struct DefaultVertexValuesStage2 : SimpleDefaultValues { }; - -// Work out the default value rule for a D3D type (expressed as the C type) and -template struct DefaultVertexValues : DefaultVertexValuesStage2 { }; -template struct DefaultVertexValues : SimpleDefaultValues { }; - -// Policy rules for use with Converter, to choose whether to use the preferred or fallback conversion. -// The fallback conversion produces an output that all D3D9 devices must support. -template struct UsePreferred { enum { type = T::preferred }; }; -template struct UseFallback { enum { type = T::fallback }; }; - -// Converter ties it all together. Given an OpenGL type/norm/size and choice of preferred/fallback conversion, -// it provides all the members of the appropriate VertexDataConverter, the D3DCAPS9::DeclTypes flag in cap flag -// and the D3DDECLTYPE member needed for the vertex declaration in declflag. -template class PreferenceRule> -struct Converter - : VertexDataConverter::type, - WidenRule >::type, size>, - ConversionRule >::type>, - DefaultVertexValues >::type>::type, normalized > > -{ -private: - enum { d3dtype = PreferenceRule< VertexTypeMapping >::type }; - enum { d3dsize = WidenRule::finalWidth }; - -public: - enum { capflag = VertexTypeFlags::capflag }; - enum { declflag = VertexTypeFlags::declflag }; -}; - -// Initialize a TranslationInfo -#define TRANSLATION(type, norm, size, preferred) \ - { \ - Converter::identity, \ - Converter::finalSize, \ - Converter::convertArray, \ - static_cast(Converter::declflag) \ - } - -#define TRANSLATION_FOR_TYPE_NORM_SIZE(type, norm, size) \ - { \ - Converter::capflag, \ - TRANSLATION(type, norm, size, UsePreferred), \ - TRANSLATION(type, norm, size, UseFallback) \ - } - -#define TRANSLATIONS_FOR_TYPE(type) \ - { \ - { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ - { TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, true, 4) }, \ - } - -#define TRANSLATIONS_FOR_TYPE_NO_NORM(type) \ - { \ - { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ - { TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 1), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 2), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 3), TRANSLATION_FOR_TYPE_NORM_SIZE(type, false, 4) }, \ - } - -const VertexBuffer9::TranslationDescription VertexBuffer9::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1] -{ - TRANSLATIONS_FOR_TYPE(GL_BYTE), - TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_BYTE), - TRANSLATIONS_FOR_TYPE(GL_SHORT), - TRANSLATIONS_FOR_TYPE(GL_UNSIGNED_SHORT), - TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FIXED), - TRANSLATIONS_FOR_TYPE_NO_NORM(GL_FLOAT) -}; - -void VertexBuffer9::initializeTranslations(DWORD declTypes) -{ - for (unsigned int i = 0; i < NUM_GL_VERTEX_ATTRIB_TYPES; i++) - { - for (unsigned int j = 0; j < 2; j++) - { - for (unsigned int k = 0; k < 4; k++) - { - if (mPossibleTranslations[i][j][k].capsFlag == 0 || (declTypes & mPossibleTranslations[i][j][k].capsFlag) != 0) - { - mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].preferredConversion; - } - else - { - mFormatConverters[i][j][k] = mPossibleTranslations[i][j][k].fallbackConversion; - } - } - } - } -} - -unsigned int VertexBuffer9::typeIndex(GLenum type) -{ - switch (type) - { - case GL_BYTE: return 0; - case GL_UNSIGNED_BYTE: return 1; - case GL_SHORT: return 2; - case GL_UNSIGNED_SHORT: return 3; - case GL_FIXED: return 4; - case GL_FLOAT: return 5; - - default: UNREACHABLE(); return 5; - } -} - -const VertexBuffer9::FormatConverter &VertexBuffer9::formatConverter(const gl::VertexAttribute &attribute) -{ - return mFormatConverters[typeIndex(attribute.mType)][attribute.mNormalized][attribute.mSize - 1]; -} - -bool VertexBuffer9::spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, - unsigned int *outSpaceRequired) -{ - unsigned int elementSize = formatConverter(attrib).outputElementSize; - - if (attrib.mArrayEnabled) - { - unsigned int elementCount = 0; - if (instances == 0 || attrib.mDivisor == 0) - { - elementCount = count; - } - else - { - if (static_cast(instances) < std::numeric_limits::max() - (attrib.mDivisor - 1)) - { - // Round up - elementCount = (static_cast(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor; - } - else - { - elementCount = static_cast(instances) / attrib.mDivisor; - } - } - - if (elementSize <= std::numeric_limits::max() / elementCount) - { - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * elementCount; - } - return true; - } - else - { - return false; - } - } - else - { - const unsigned int elementSize = 4; - if (outSpaceRequired) - { - *outSpaceRequired = elementSize * 4; - } - return true; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h deleted file mode 100644 index 2f88117bda..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexBuffer9.h +++ /dev/null @@ -1,91 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexBuffer9.h: Defines the D3D9 VertexBuffer implementation. - -#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ -#define LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ - -#include "libGLESv2/renderer/VertexBuffer.h" - -namespace rx -{ -class Renderer9; - -class VertexBuffer9 : public VertexBuffer -{ - public: - explicit VertexBuffer9(rx::Renderer9 *const renderer); - virtual ~VertexBuffer9(); - - virtual bool initialize(unsigned int size, bool dynamicUsage); - - static VertexBuffer9 *makeVertexBuffer9(VertexBuffer *vertexBuffer); - - virtual bool storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count, GLsizei instances, - unsigned int offset); - virtual bool storeRawData(const void* data, unsigned int size, unsigned int offset); - - virtual bool getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count, GLsizei instances, unsigned int *outSpaceRequired) const; - - virtual bool requiresConversion(const gl::VertexAttribute &attrib) const; - - unsigned int getVertexSize(const gl::VertexAttribute &attrib) const; - D3DDECLTYPE getDeclType(const gl::VertexAttribute &attrib) const; - - virtual unsigned int getBufferSize() const; - virtual bool setBufferSize(unsigned int size); - virtual bool discard(); - - IDirect3DVertexBuffer9 *getBuffer() const; - - private: - DISALLOW_COPY_AND_ASSIGN(VertexBuffer9); - - rx::Renderer9 *const mRenderer; - - IDirect3DVertexBuffer9 *mVertexBuffer; - unsigned int mBufferSize; - bool mDynamicUsage; - - // Attribute format conversion - enum { NUM_GL_VERTEX_ATTRIB_TYPES = 6 }; - - struct FormatConverter - { - bool identity; - std::size_t outputElementSize; - void (*convertArray)(const void *in, std::size_t stride, std::size_t n, void *out); - D3DDECLTYPE d3dDeclType; - }; - - static bool mTranslationsInitialized; - static void initializeTranslations(DWORD declTypes); - - // [GL types as enumerated by typeIndex()][normalized][size - 1] - static FormatConverter mFormatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; - - struct TranslationDescription - { - DWORD capsFlag; - FormatConverter preferredConversion; - FormatConverter fallbackConversion; - }; - - // This table is used to generate mFormatConverters. - // [GL types as enumerated by typeIndex()][normalized][size - 1] - static const TranslationDescription mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4]; - - static unsigned int typeIndex(GLenum type); - static const FormatConverter &formatConverter(const gl::VertexAttribute &attribute); - - static bool spaceRequired(const gl::VertexAttribute &attrib, std::size_t count, GLsizei instances, - unsigned int *outSpaceRequired); -}; - -} - -#endif // LIBGLESV2_RENDERER_VERTEXBUFFER9_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp deleted file mode 100644 index e5c8a14232..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.cpp +++ /dev/null @@ -1,217 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations. - -#include "libGLESv2/ProgramBinary.h" -#include "libGLESv2/Context.h" -#include "libGLESv2/renderer/d3d9/VertexBuffer9.h" -#include "libGLESv2/renderer/d3d9/VertexDeclarationCache.h" - -namespace rx -{ - -VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0) -{ - for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) - { - mVertexDeclCache[i].vertexDeclaration = NULL; - mVertexDeclCache[i].lruCount = 0; - } - - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mAppliedVBs[i].serial = 0; - } - - mLastSetVDecl = NULL; - mInstancingEnabled = true; -} - -VertexDeclarationCache::~VertexDeclarationCache() -{ - for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) - { - if (mVertexDeclCache[i].vertexDeclaration) - { - mVertexDeclCache[i].vertexDeclaration->Release(); - } - } -} - -GLenum VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw) -{ - *repeatDraw = 1; - - int indexedAttribute = gl::MAX_VERTEX_ATTRIBS; - int instancedAttribute = gl::MAX_VERTEX_ATTRIBS; - - if (instances > 0) - { - // Find an indexed attribute to be mapped to D3D stream 0 - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - if (attributes[i].active) - { - if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor == 0) - { - indexedAttribute = i; - } - else if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS && attributes[i].divisor != 0) - { - instancedAttribute = i; - } - if (indexedAttribute != gl::MAX_VERTEX_ATTRIBS && instancedAttribute != gl::MAX_VERTEX_ATTRIBS) - break; // Found both an indexed and instanced attribute - } - } - - if (indexedAttribute == gl::MAX_VERTEX_ATTRIBS) - { - return GL_INVALID_OPERATION; - } - } - - D3DVERTEXELEMENT9 elements[gl::MAX_VERTEX_ATTRIBS + 1]; - D3DVERTEXELEMENT9 *element = &elements[0]; - - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - if (attributes[i].active) - { - // Directly binding the storage buffer is not supported for d3d9 - ASSERT(attributes[i].storage == NULL); - - int stream = i; - - if (instances > 0) - { - // Due to a bug on ATI cards we can't enable instancing when none of the attributes are instanced. - if (instancedAttribute == gl::MAX_VERTEX_ATTRIBS) - { - *repeatDraw = instances; - } - else - { - if (i == indexedAttribute) - { - stream = 0; - } - else if (i == 0) - { - stream = indexedAttribute; - } - - UINT frequency = 1; - - if (attributes[i].divisor == 0) - { - frequency = D3DSTREAMSOURCE_INDEXEDDATA | instances; - } - else - { - frequency = D3DSTREAMSOURCE_INSTANCEDATA | attributes[i].divisor; - } - - device->SetStreamSourceFreq(stream, frequency); - mInstancingEnabled = true; - } - } - - VertexBuffer9 *vertexBuffer = VertexBuffer9::makeVertexBuffer9(attributes[i].vertexBuffer); - - if (mAppliedVBs[stream].serial != attributes[i].serial || - mAppliedVBs[stream].stride != attributes[i].stride || - mAppliedVBs[stream].offset != attributes[i].offset) - { - device->SetStreamSource(stream, vertexBuffer->getBuffer(), attributes[i].offset, attributes[i].stride); - mAppliedVBs[stream].serial = attributes[i].serial; - mAppliedVBs[stream].stride = attributes[i].stride; - mAppliedVBs[stream].offset = attributes[i].offset; - } - - element->Stream = stream; - element->Offset = 0; - element->Type = attributes[i].attribute->mArrayEnabled ? vertexBuffer->getDeclType(*attributes[i].attribute) : D3DDECLTYPE_FLOAT4; - element->Method = D3DDECLMETHOD_DEFAULT; - element->Usage = D3DDECLUSAGE_TEXCOORD; - element->UsageIndex = programBinary->getSemanticIndex(i); - element++; - } - } - - if (instances == 0 || instancedAttribute == gl::MAX_VERTEX_ATTRIBS) - { - if (mInstancingEnabled) - { - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - device->SetStreamSourceFreq(i, 1); - } - - mInstancingEnabled = false; - } - } - - static const D3DVERTEXELEMENT9 end = D3DDECL_END(); - *(element++) = end; - - for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) - { - VertexDeclCacheEntry *entry = &mVertexDeclCache[i]; - if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration) - { - entry->lruCount = ++mMaxLru; - if(entry->vertexDeclaration != mLastSetVDecl) - { - device->SetVertexDeclaration(entry->vertexDeclaration); - mLastSetVDecl = entry->vertexDeclaration; - } - - return GL_NO_ERROR; - } - } - - VertexDeclCacheEntry *lastCache = mVertexDeclCache; - - for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++) - { - if (mVertexDeclCache[i].lruCount < lastCache->lruCount) - { - lastCache = &mVertexDeclCache[i]; - } - } - - if (lastCache->vertexDeclaration != NULL) - { - lastCache->vertexDeclaration->Release(); - lastCache->vertexDeclaration = NULL; - // mLastSetVDecl is set to the replacement, so we don't have to worry - // about it. - } - - memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)); - device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration); - device->SetVertexDeclaration(lastCache->vertexDeclaration); - mLastSetVDecl = lastCache->vertexDeclaration; - lastCache->lruCount = ++mMaxLru; - - return GL_NO_ERROR; -} - -void VertexDeclarationCache::markStateDirty() -{ - for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++) - { - mAppliedVBs[i].serial = 0; - } - - mLastSetVDecl = NULL; - mInstancingEnabled = true; // Forces it to be disabled when not used -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h deleted file mode 100644 index 3fc024a9ba..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/VertexDeclarationCache.h +++ /dev/null @@ -1,58 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// VertexDeclarationCache.h: Defines a helper class to construct and cache vertex declarations. - -#ifndef LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ -#define LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ - -#include "libGLESv2/renderer/VertexDataManager.h" - -namespace gl -{ -class VertexDataManager; -} - -namespace rx -{ - -class VertexDeclarationCache -{ - public: - VertexDeclarationCache(); - ~VertexDeclarationCache(); - - GLenum applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw); - - void markStateDirty(); - - private: - UINT mMaxLru; - - enum { NUM_VERTEX_DECL_CACHE_ENTRIES = 32 }; - - struct VBData - { - unsigned int serial; - unsigned int stride; - unsigned int offset; - }; - - VBData mAppliedVBs[gl::MAX_VERTEX_ATTRIBS]; - IDirect3DVertexDeclaration9 *mLastSetVDecl; - bool mInstancingEnabled; - - struct VertexDeclCacheEntry - { - D3DVERTEXELEMENT9 cachedElements[gl::MAX_VERTEX_ATTRIBS + 1]; - UINT lruCount; - IDirect3DVertexDeclaration9 *vertexDeclaration; - } mVertexDeclCache[NUM_VERTEX_DECL_CACHE_ENTRIES]; -}; - -} - -#endif // LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp deleted file mode 100644 index b7f2ffb1d9..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.cpp +++ /dev/null @@ -1,500 +0,0 @@ -#include "precompiled.h" -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// renderer9_utils.cpp: Conversion functions and other utility routines -// specific to the D3D9 renderer. - -#include "libGLESv2/renderer/d3d9/renderer9_utils.h" -#include "libGLESv2/mathutil.h" -#include "libGLESv2/Context.h" - -#include "common/debug.h" - -namespace gl_d3d9 -{ - -D3DCMPFUNC ConvertComparison(GLenum comparison) -{ - D3DCMPFUNC d3dComp = D3DCMP_ALWAYS; - switch (comparison) - { - case GL_NEVER: d3dComp = D3DCMP_NEVER; break; - case GL_ALWAYS: d3dComp = D3DCMP_ALWAYS; break; - case GL_LESS: d3dComp = D3DCMP_LESS; break; - case GL_LEQUAL: d3dComp = D3DCMP_LESSEQUAL; break; - case GL_EQUAL: d3dComp = D3DCMP_EQUAL; break; - case GL_GREATER: d3dComp = D3DCMP_GREATER; break; - case GL_GEQUAL: d3dComp = D3DCMP_GREATEREQUAL; break; - case GL_NOTEQUAL: d3dComp = D3DCMP_NOTEQUAL; break; - default: UNREACHABLE(); - } - - return d3dComp; -} - -D3DCOLOR ConvertColor(gl::Color color) -{ - return D3DCOLOR_RGBA(gl::unorm<8>(color.red), - gl::unorm<8>(color.green), - gl::unorm<8>(color.blue), - gl::unorm<8>(color.alpha)); -} - -D3DBLEND ConvertBlendFunc(GLenum blend) -{ - D3DBLEND d3dBlend = D3DBLEND_ZERO; - - switch (blend) - { - case GL_ZERO: d3dBlend = D3DBLEND_ZERO; break; - case GL_ONE: d3dBlend = D3DBLEND_ONE; break; - case GL_SRC_COLOR: d3dBlend = D3DBLEND_SRCCOLOR; break; - case GL_ONE_MINUS_SRC_COLOR: d3dBlend = D3DBLEND_INVSRCCOLOR; break; - case GL_DST_COLOR: d3dBlend = D3DBLEND_DESTCOLOR; break; - case GL_ONE_MINUS_DST_COLOR: d3dBlend = D3DBLEND_INVDESTCOLOR; break; - case GL_SRC_ALPHA: d3dBlend = D3DBLEND_SRCALPHA; break; - case GL_ONE_MINUS_SRC_ALPHA: d3dBlend = D3DBLEND_INVSRCALPHA; break; - case GL_DST_ALPHA: d3dBlend = D3DBLEND_DESTALPHA; break; - case GL_ONE_MINUS_DST_ALPHA: d3dBlend = D3DBLEND_INVDESTALPHA; break; - case GL_CONSTANT_COLOR: d3dBlend = D3DBLEND_BLENDFACTOR; break; - case GL_ONE_MINUS_CONSTANT_COLOR: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; - case GL_CONSTANT_ALPHA: d3dBlend = D3DBLEND_BLENDFACTOR; break; - case GL_ONE_MINUS_CONSTANT_ALPHA: d3dBlend = D3DBLEND_INVBLENDFACTOR; break; - case GL_SRC_ALPHA_SATURATE: d3dBlend = D3DBLEND_SRCALPHASAT; break; - default: UNREACHABLE(); - } - - return d3dBlend; -} - -D3DBLENDOP ConvertBlendOp(GLenum blendOp) -{ - D3DBLENDOP d3dBlendOp = D3DBLENDOP_ADD; - - switch (blendOp) - { - case GL_FUNC_ADD: d3dBlendOp = D3DBLENDOP_ADD; break; - case GL_FUNC_SUBTRACT: d3dBlendOp = D3DBLENDOP_SUBTRACT; break; - case GL_FUNC_REVERSE_SUBTRACT: d3dBlendOp = D3DBLENDOP_REVSUBTRACT; break; - default: UNREACHABLE(); - } - - return d3dBlendOp; -} - -D3DSTENCILOP ConvertStencilOp(GLenum stencilOp) -{ - D3DSTENCILOP d3dStencilOp = D3DSTENCILOP_KEEP; - - switch (stencilOp) - { - case GL_ZERO: d3dStencilOp = D3DSTENCILOP_ZERO; break; - case GL_KEEP: d3dStencilOp = D3DSTENCILOP_KEEP; break; - case GL_REPLACE: d3dStencilOp = D3DSTENCILOP_REPLACE; break; - case GL_INCR: d3dStencilOp = D3DSTENCILOP_INCRSAT; break; - case GL_DECR: d3dStencilOp = D3DSTENCILOP_DECRSAT; break; - case GL_INVERT: d3dStencilOp = D3DSTENCILOP_INVERT; break; - case GL_INCR_WRAP: d3dStencilOp = D3DSTENCILOP_INCR; break; - case GL_DECR_WRAP: d3dStencilOp = D3DSTENCILOP_DECR; break; - default: UNREACHABLE(); - } - - return d3dStencilOp; -} - -D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap) -{ - D3DTEXTUREADDRESS d3dWrap = D3DTADDRESS_WRAP; - - switch (wrap) - { - case GL_REPEAT: d3dWrap = D3DTADDRESS_WRAP; break; - case GL_CLAMP_TO_EDGE: d3dWrap = D3DTADDRESS_CLAMP; break; - case GL_MIRRORED_REPEAT: d3dWrap = D3DTADDRESS_MIRROR; break; - default: UNREACHABLE(); - } - - return d3dWrap; -} - -D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace) -{ - D3DCULL cull = D3DCULL_CCW; - switch (cullFace) - { - case GL_FRONT: - cull = (frontFace == GL_CCW ? D3DCULL_CW : D3DCULL_CCW); - break; - case GL_BACK: - cull = (frontFace == GL_CCW ? D3DCULL_CCW : D3DCULL_CW); - break; - case GL_FRONT_AND_BACK: - cull = D3DCULL_NONE; // culling will be handled during draw - break; - default: UNREACHABLE(); - } - - return cull; -} - -D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace) -{ - D3DCUBEMAP_FACES face = D3DCUBEMAP_FACE_POSITIVE_X; - - switch (cubeFace) - { - case GL_TEXTURE_CUBE_MAP_POSITIVE_X: - face = D3DCUBEMAP_FACE_POSITIVE_X; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: - face = D3DCUBEMAP_FACE_NEGATIVE_X; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: - face = D3DCUBEMAP_FACE_POSITIVE_Y; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: - face = D3DCUBEMAP_FACE_NEGATIVE_Y; - break; - case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: - face = D3DCUBEMAP_FACE_POSITIVE_Z; - break; - case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: - face = D3DCUBEMAP_FACE_NEGATIVE_Z; - break; - default: UNREACHABLE(); - } - - return face; -} - -DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha) -{ - return (red ? D3DCOLORWRITEENABLE_RED : 0) | - (green ? D3DCOLORWRITEENABLE_GREEN : 0) | - (blue ? D3DCOLORWRITEENABLE_BLUE : 0) | - (alpha ? D3DCOLORWRITEENABLE_ALPHA : 0); -} - -D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy) -{ - if (maxAnisotropy > 1.0f) - { - return D3DTEXF_ANISOTROPIC; - } - - D3DTEXTUREFILTERTYPE d3dMagFilter = D3DTEXF_POINT; - switch (magFilter) - { - case GL_NEAREST: d3dMagFilter = D3DTEXF_POINT; break; - case GL_LINEAR: d3dMagFilter = D3DTEXF_LINEAR; break; - default: UNREACHABLE(); - } - - return d3dMagFilter; -} - -void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy) -{ - switch (minFilter) - { - case GL_NEAREST: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_NONE; - break; - case GL_LINEAR: - *d3dMinFilter = D3DTEXF_LINEAR; - *d3dMipFilter = D3DTEXF_NONE; - break; - case GL_NEAREST_MIPMAP_NEAREST: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_POINT; - break; - case GL_LINEAR_MIPMAP_NEAREST: - *d3dMinFilter = D3DTEXF_LINEAR; - *d3dMipFilter = D3DTEXF_POINT; - break; - case GL_NEAREST_MIPMAP_LINEAR: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_LINEAR; - break; - case GL_LINEAR_MIPMAP_LINEAR: - *d3dMinFilter = D3DTEXF_LINEAR; - *d3dMipFilter = D3DTEXF_LINEAR; - break; - default: - *d3dMinFilter = D3DTEXF_POINT; - *d3dMipFilter = D3DTEXF_NONE; - UNREACHABLE(); - } - - if (maxAnisotropy > 1.0f) - { - *d3dMinFilter = D3DTEXF_ANISOTROPIC; - } -} - -D3DFORMAT ConvertRenderbufferFormat(GLenum format) -{ - switch (format) - { - case GL_NONE: return D3DFMT_NULL; - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGBA8_OES: return D3DFMT_A8R8G8B8; - case GL_RGB565: return D3DFMT_R5G6B5; - case GL_RGB8_OES: return D3DFMT_X8R8G8B8; - case GL_DEPTH_COMPONENT16: - case GL_STENCIL_INDEX8: - case GL_DEPTH24_STENCIL8_OES: return D3DFMT_D24S8; - default: UNREACHABLE(); return D3DFMT_A8R8G8B8; - } -} - -D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples) -{ - if (samples <= 1) - return D3DMULTISAMPLE_NONE; - else - return (D3DMULTISAMPLE_TYPE)samples; -} - -} - -namespace d3d9_gl -{ - -unsigned int GetStencilSize(D3DFORMAT stencilFormat) -{ - if (stencilFormat == D3DFMT_INTZ) - { - return 8; - } - switch(stencilFormat) - { - case D3DFMT_D24FS8: - case D3DFMT_D24S8: - return 8; - case D3DFMT_D24X4S4: - return 4; - case D3DFMT_D15S1: - return 1; - case D3DFMT_D16_LOCKABLE: - case D3DFMT_D32: - case D3DFMT_D24X8: - case D3DFMT_D32F_LOCKABLE: - case D3DFMT_D16: - return 0; - //case D3DFMT_D32_LOCKABLE: return 0; // DirectX 9Ex only - //case D3DFMT_S8_LOCKABLE: return 8; // DirectX 9Ex only - default: - return 0; - } -} - -unsigned int GetAlphaSize(D3DFORMAT colorFormat) -{ - switch (colorFormat) - { - case D3DFMT_A16B16G16R16F: - return 16; - case D3DFMT_A32B32G32R32F: - return 32; - case D3DFMT_A2R10G10B10: - return 2; - case D3DFMT_A8R8G8B8: - return 8; - case D3DFMT_A1R5G5B5: - return 1; - case D3DFMT_X8R8G8B8: - case D3DFMT_R5G6B5: - return 0; - default: - return 0; - } -} - -GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type) -{ - if (type == D3DMULTISAMPLE_NONMASKABLE) - return 0; - else - return type; -} - -bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format) -{ - switch (d3dformat) - { - case D3DFMT_L8: - return (format == GL_LUMINANCE); - case D3DFMT_A8L8: - return (format == GL_LUMINANCE_ALPHA); - case D3DFMT_DXT1: - return (format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT); - case D3DFMT_DXT3: - return (format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE); - case D3DFMT_DXT5: - return (format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE); - case D3DFMT_A8R8G8B8: - case D3DFMT_A16B16G16R16F: - case D3DFMT_A32B32G32R32F: - return (format == GL_RGBA || format == GL_BGRA_EXT); - case D3DFMT_X8R8G8B8: - return (format == GL_RGB); - default: - if (d3dformat == D3DFMT_INTZ && gl::IsDepthTexture(format)) - return true; - return false; - } -} - -GLenum ConvertBackBufferFormat(D3DFORMAT format) -{ - switch (format) - { - case D3DFMT_A4R4G4B4: return GL_RGBA4; - case D3DFMT_A8R8G8B8: return GL_RGBA8_OES; - case D3DFMT_A1R5G5B5: return GL_RGB5_A1; - case D3DFMT_R5G6B5: return GL_RGB565; - case D3DFMT_X8R8G8B8: return GL_RGB8_OES; - default: - UNREACHABLE(); - } - - return GL_RGBA4; -} - -GLenum ConvertDepthStencilFormat(D3DFORMAT format) -{ - if (format == D3DFMT_INTZ) - { - return GL_DEPTH24_STENCIL8_OES; - } - switch (format) - { - case D3DFMT_D16: - case D3DFMT_D24X8: - return GL_DEPTH_COMPONENT16; - case D3DFMT_D24S8: - return GL_DEPTH24_STENCIL8_OES; - case D3DFMT_UNKNOWN: - return GL_NONE; - default: - UNREACHABLE(); - } - - return GL_DEPTH24_STENCIL8_OES; -} - -GLenum ConvertRenderTargetFormat(D3DFORMAT format) -{ - if (format == D3DFMT_INTZ) - { - return GL_DEPTH24_STENCIL8_OES; - } - - switch (format) - { - case D3DFMT_A4R4G4B4: return GL_RGBA4; - case D3DFMT_A8R8G8B8: return GL_RGBA8_OES; - case D3DFMT_A1R5G5B5: return GL_RGB5_A1; - case D3DFMT_R5G6B5: return GL_RGB565; - case D3DFMT_X8R8G8B8: return GL_RGB8_OES; - case D3DFMT_D16: - case D3DFMT_D24X8: - return GL_DEPTH_COMPONENT16; - case D3DFMT_D24S8: - return GL_DEPTH24_STENCIL8_OES; - case D3DFMT_UNKNOWN: - return GL_NONE; - default: - UNREACHABLE(); - } - - return GL_RGBA4; -} - -GLenum GetEquivalentFormat(D3DFORMAT format) -{ - if (format == D3DFMT_INTZ) - return GL_DEPTH24_STENCIL8_OES; - if (format == D3DFMT_NULL) - return GL_NONE; - - switch (format) - { - case D3DFMT_A4R4G4B4: return GL_RGBA4; - case D3DFMT_A8R8G8B8: return GL_RGBA8_OES; - case D3DFMT_A1R5G5B5: return GL_RGB5_A1; - case D3DFMT_R5G6B5: return GL_RGB565; - case D3DFMT_X8R8G8B8: return GL_RGB8_OES; - case D3DFMT_D16: return GL_DEPTH_COMPONENT16; - case D3DFMT_D24S8: return GL_DEPTH24_STENCIL8_OES; - case D3DFMT_UNKNOWN: return GL_NONE; - case D3DFMT_DXT1: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - case D3DFMT_DXT3: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE; - case D3DFMT_DXT5: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE; - case D3DFMT_A32B32G32R32F: return GL_RGBA32F_EXT; - case D3DFMT_A16B16G16R16F: return GL_RGBA16F_EXT; - case D3DFMT_L8: return GL_LUMINANCE8_EXT; - case D3DFMT_A8L8: return GL_LUMINANCE8_ALPHA8_EXT; - default: UNREACHABLE(); - return GL_NONE; - } -} - -} - -namespace d3d9 -{ - -bool IsCompressedFormat(D3DFORMAT surfaceFormat) -{ - switch(surfaceFormat) - { - case D3DFMT_DXT1: - case D3DFMT_DXT2: - case D3DFMT_DXT3: - case D3DFMT_DXT4: - case D3DFMT_DXT5: - return true; - default: - return false; - } -} - -size_t ComputeRowSize(D3DFORMAT format, unsigned int width) -{ - if (format == D3DFMT_INTZ) - { - return 4 * width; - } - switch (format) - { - case D3DFMT_L8: - return 1 * width; - case D3DFMT_A8L8: - return 2 * width; - case D3DFMT_X8R8G8B8: - case D3DFMT_A8R8G8B8: - return 4 * width; - case D3DFMT_A16B16G16R16F: - return 8 * width; - case D3DFMT_A32B32G32R32F: - return 16 * width; - case D3DFMT_DXT1: - return 8 * ((width + 3) / 4); - case D3DFMT_DXT3: - case D3DFMT_DXT5: - return 16 * ((width + 3) / 4); - default: - UNREACHABLE(); - return 0; - } -} - -} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h deleted file mode 100644 index bf6cdf1ea6..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/renderer9_utils.h +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// renderer9_utils.h: Conversion functions and other utility routines -// specific to the D3D9 renderer - -#ifndef LIBGLESV2_RENDERER_RENDERER9_UTILS_H -#define LIBGLESV2_RENDERER_RENDERER9_UTILS_H - -#include "libGLESv2/utilities.h" - -const D3DFORMAT D3DFMT_INTZ = ((D3DFORMAT)(MAKEFOURCC('I','N','T','Z'))); -const D3DFORMAT D3DFMT_NULL = ((D3DFORMAT)(MAKEFOURCC('N','U','L','L'))); - -namespace gl_d3d9 -{ - -D3DCMPFUNC ConvertComparison(GLenum comparison); -D3DCOLOR ConvertColor(gl::Color color); -D3DBLEND ConvertBlendFunc(GLenum blend); -D3DBLENDOP ConvertBlendOp(GLenum blendOp); -D3DSTENCILOP ConvertStencilOp(GLenum stencilOp); -D3DTEXTUREADDRESS ConvertTextureWrap(GLenum wrap); -D3DCULL ConvertCullMode(GLenum cullFace, GLenum frontFace); -D3DCUBEMAP_FACES ConvertCubeFace(GLenum cubeFace); -DWORD ConvertColorMask(bool red, bool green, bool blue, bool alpha); -D3DTEXTUREFILTERTYPE ConvertMagFilter(GLenum magFilter, float maxAnisotropy); -void ConvertMinFilter(GLenum minFilter, D3DTEXTUREFILTERTYPE *d3dMinFilter, D3DTEXTUREFILTERTYPE *d3dMipFilter, float maxAnisotropy); -D3DFORMAT ConvertRenderbufferFormat(GLenum format); -D3DMULTISAMPLE_TYPE GetMultisampleTypeFromSamples(GLsizei samples); - -} - -namespace d3d9_gl -{ - -GLuint GetAlphaSize(D3DFORMAT colorFormat); -GLuint GetStencilSize(D3DFORMAT stencilFormat); - -GLsizei GetSamplesFromMultisampleType(D3DMULTISAMPLE_TYPE type); - -bool IsFormatChannelEquivalent(D3DFORMAT d3dformat, GLenum format); -GLenum ConvertBackBufferFormat(D3DFORMAT format); -GLenum ConvertDepthStencilFormat(D3DFORMAT format); -GLenum ConvertRenderTargetFormat(D3DFORMAT format); -GLenum GetEquivalentFormat(D3DFORMAT format); - -} - -namespace d3d9 -{ -bool IsCompressedFormat(D3DFORMAT format); -size_t ComputeRowSize(D3DFORMAT format, unsigned int width); - -inline bool isDeviceLostError(HRESULT errorCode) -{ - switch (errorCode) - { - case D3DERR_DRIVERINTERNALERROR: - case D3DERR_DEVICELOST: - case D3DERR_DEVICEHUNG: - case D3DERR_DEVICEREMOVED: - return true; - default: - return false; - } -} - -} - -#endif // LIBGLESV2_RENDERER_RENDERER9_UTILS_H diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps deleted file mode 100644 index dcb3bd0e76..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.ps +++ /dev/null @@ -1,39 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -sampler2D tex : s0; - -uniform float4 mode : c0; - -// Passthrough Pixel Shader -// Outputs texture 0 sampled at texcoord 0. -float4 passthroughps(float4 texcoord : TEXCOORD0) : COLOR -{ - return tex2D(tex, texcoord.xy); -}; - -// Luminance Conversion Pixel Shader -// Outputs sample(tex0, tc0).rrra. -// For LA output (pass A) set C0.X = 1, C0.Y = 0. -// For L output (A = 1) set C0.X = 0, C0.Y = 1. -float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR -{ - float4 tmp = tex2D(tex, texcoord.xy); - tmp.w = tmp.w * mode.x + mode.y; - return tmp.xxxw; -}; - -// RGB/A Component Mask Pixel Shader -// Outputs sample(tex0, tc0) with options to force RGB = 0 and/or A = 1. -// To force RGB = 0, set C0.X = 0, otherwise C0.X = 1. -// To force A = 1, set C0.Z = 0, C0.W = 1, otherwise C0.Z = 1, C0.W = 0. -float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR -{ - float4 tmp = tex2D(tex, texcoord.xy); - tmp.xyz = tmp.xyz * mode.x; - tmp.w = tmp.w * mode.z + mode.w; - return tmp; -}; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs deleted file mode 100644 index 3a36980b93..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/shaders/Blit.vs +++ /dev/null @@ -1,43 +0,0 @@ -// -// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -struct VS_OUTPUT -{ - float4 position : POSITION; - float4 texcoord : TEXCOORD0; -}; - -uniform float4 halfPixelSize : c0; - -// Standard Vertex Shader -// Input 0 is the homogenous position. -// Outputs the homogenous position as-is. -// Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right. -// C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0. -VS_OUTPUT standardvs(in float4 position : POSITION) -{ - VS_OUTPUT Out; - - Out.position = position + halfPixelSize; - Out.texcoord = position * float4(0.5, -0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0); - - return Out; -}; - -// Flip Y Vertex Shader -// Input 0 is the homogenous position. -// Outputs the homogenous position as-is. -// Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right. -// C0.XY must be the half-pixel width and height. C0.ZW must be 0. -VS_OUTPUT flipyvs(in float4 position : POSITION) -{ - VS_OUTPUT Out; - - Out.position = position + halfPixelSize; - Out.texcoord = position * float4(0.5, 0.5, 1.0, 1.0) + float4(0.5, 0.5, 0, 0); - - return Out; -}; diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/vertexconversion.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/vertexconversion.h deleted file mode 100644 index 590b9d48a3..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d9/vertexconversion.h +++ /dev/null @@ -1,203 +0,0 @@ -// -// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// vertexconversion.h: A library of vertex conversion classes that can be used to build -// the FormatConverter objects used by the buffer conversion system. - -#ifndef LIBGLESV2_VERTEXCONVERSION_H_ -#define LIBGLESV2_VERTEXCONVERSION_H_ - -namespace rx -{ - -// Conversion types: -// static const bool identity: true if this is an identity transform, false otherwise -// static U convert(T): convert a single element from the input type to the output type -// typedef ... OutputType: the type produced by this conversion - -template -struct Identity -{ - static const bool identity = true; - - typedef T OutputType; - - static T convert(T x) - { - return x; - } -}; - -template -struct Cast -{ - static const bool identity = false; - - typedef ToT OutputType; - - static ToT convert(FromT x) - { - return static_cast(x); - } -}; - -template -struct Cast -{ - static const bool identity = true; - - typedef T OutputType; - - static T convert(T x) - { - return static_cast(x); - } -}; - -template -struct Normalize -{ - static const bool identity = false; - - typedef float OutputType; - - static float convert(T x) - { - typedef std::numeric_limits NL; - float f = static_cast(x); - - if (NL::is_signed) - { - // const float => VC2008 computes it at compile time - // static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that. - const float divisor = 1.0f/(2*static_cast(NL::max())+1); - return (2*f+1)*divisor; - } - else - { - return f/NL::max(); - } - } -}; - -template -struct FixedToFloat -{ - static const bool identity = false; - - typedef float OutputType; - - static float convert(FromType x) - { - const float divisor = 1.0f / static_cast(static_cast(1) << ScaleBits); - return static_cast(x) * divisor; - } -}; - -// Widen types: -// static const unsigned int initialWidth: number of components before conversion -// static const unsigned int finalWidth: number of components after conversion - -// Float is supported at any size. -template -struct NoWiden -{ - static const std::size_t initialWidth = N; - static const std::size_t finalWidth = N; -}; - -// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components -template -struct WidenToEven -{ - static const std::size_t initialWidth = N; - static const std::size_t finalWidth = N+(N&1); -}; - -template -struct WidenToFour -{ - static const std::size_t initialWidth = N; - static const std::size_t finalWidth = 4; -}; - -// Most types have 0 and 1 that are just that. -template -struct SimpleDefaultValues -{ - static T zero() { return static_cast(0); } - static T one() { return static_cast(1); } -}; - -// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value. -template -struct NormalizedDefaultValues -{ - static T zero() { return static_cast(0); } - static T one() { return std::numeric_limits::max(); } -}; - -// Converter: -// static const bool identity: true if this is an identity transform (with no widening) -// static const std::size_t finalSize: number of bytes per output vertex -// static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert an array of vertices. Input may be strided, but output will be unstrided. - -template > -struct VertexDataConverter -{ - typedef typename Converter::OutputType OutputType; - typedef InT InputType; - - static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity; - static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType); - - static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out) - { - for (std::size_t i = 0; i < n; i++) - { - const InputType *ein = pointerAddBytes(in, i * stride); - - copyComponent(out, ein, 0, static_cast(DefaultValueRule::zero())); - copyComponent(out, ein, 1, static_cast(DefaultValueRule::zero())); - copyComponent(out, ein, 2, static_cast(DefaultValueRule::zero())); - copyComponent(out, ein, 3, static_cast(DefaultValueRule::one())); - - out += WidenRule::finalWidth; - } - } - - static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out) - { - return convertArray(static_cast(in), stride, n, static_cast(out)); - } - - private: - // Advance the given pointer by a number of bytes (not pointed-to elements). - template - static T *pointerAddBytes(T *basePtr, std::size_t numBytes) - { - return reinterpret_cast(reinterpret_cast(basePtr) + numBytes); - } - - static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue) - { - if (WidenRule::finalWidth > elementindex) - { - if (WidenRule::initialWidth > elementindex) - { - out[elementindex] = Converter::convert(in[elementindex]); - } - else - { - out[elementindex] = defaultvalue; - } - } - } -}; - -} - -#endif // LIBGLESV2_VERTEXCONVERSION_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h b/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h index 8e1973605b..a57b00d444 100644 --- a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h +++ b/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.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. // @@ -10,194 +10,19 @@ #ifndef LIBGLESV2_RENDERER_GENERATEMIP_H_ #define LIBGLESV2_RENDERER_GENERATEMIP_H_ -#include "libGLESv2/mathutil.h" +#include "libGLESv2/renderer/imageformats.h" +#include "libGLESv2/angletypes.h" namespace rx { -struct L8 -{ - unsigned char L; - - static void average(L8 *dst, const L8 *src1, const L8 *src2) - { - dst->L = ((src1->L ^ src2->L) >> 1) + (src1->L & src2->L); - } -}; - -typedef L8 R8; // R8 type is functionally equivalent for mip purposes -typedef L8 A8; // A8 type is functionally equivalent for mip purposes - -struct A8L8 -{ - unsigned char L; - unsigned char A; - - static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2) - { - *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); - } -}; - -typedef A8L8 R8G8; // R8G8 type is functionally equivalent for mip purposes - -struct A8R8G8B8 -{ - unsigned char B; - unsigned char G; - unsigned char R; - unsigned char A; - - static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2) - { - *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); - } -}; - -typedef A8R8G8B8 R8G8B8A8; // R8G8B8A8 type is functionally equivalent for mip purposes - -struct A16B16G16R16F -{ - unsigned short R; - unsigned short G; - unsigned short B; - unsigned short A; - - static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2) - { - dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f); - dst->G = gl::float32ToFloat16((gl::float16ToFloat32(src1->G) + gl::float16ToFloat32(src2->G)) * 0.5f); - dst->B = gl::float32ToFloat16((gl::float16ToFloat32(src1->B) + gl::float16ToFloat32(src2->B)) * 0.5f); - dst->A = gl::float32ToFloat16((gl::float16ToFloat32(src1->A) + gl::float16ToFloat32(src2->A)) * 0.5f); - } -}; - -struct R16F -{ - unsigned short R; - - static void average(R16F *dst, const R16F *src1, const R16F *src2) - { - dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f); - } -}; - -struct R16G16F -{ - unsigned short R; - unsigned short G; - - static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2) - { - dst->R = gl::float32ToFloat16((gl::float16ToFloat32(src1->R) + gl::float16ToFloat32(src2->R)) * 0.5f); - dst->G = gl::float32ToFloat16((gl::float16ToFloat32(src1->G) + gl::float16ToFloat32(src2->G)) * 0.5f); - } -}; - -struct A32B32G32R32F -{ - float R; - float G; - float B; - float A; - - static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2) - { - dst->R = (src1->R + src2->R) * 0.5f; - dst->G = (src1->G + src2->G) * 0.5f; - dst->B = (src1->B + src2->B) * 0.5f; - dst->A = (src1->A + src2->A) * 0.5f; - } -}; - -struct R32F -{ - float R; - - static void average(R32F *dst, const R32F *src1, const R32F *src2) - { - dst->R = (src1->R + src2->R) * 0.5f; - } -}; - -struct R32G32F -{ - float R; - float G; - - static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2) - { - dst->R = (src1->R + src2->R) * 0.5f; - dst->G = (src1->G + src2->G) * 0.5f; - } -}; - -struct R32G32B32F -{ - float R; - float G; - float B; - - static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2) - { - dst->R = (src1->R + src2->R) * 0.5f; - dst->G = (src1->G + src2->G) * 0.5f; - dst->B = (src1->B + src2->B) * 0.5f; - } -}; template -static void GenerateMip(unsigned int sourceWidth, unsigned int sourceHeight, - const unsigned char *sourceData, int sourcePitch, - unsigned char *destData, int destPitch) -{ - unsigned int mipWidth = std::max(1U, sourceWidth >> 1); - unsigned int mipHeight = std::max(1U, sourceHeight >> 1); - - if (sourceHeight == 1) - { - ASSERT(sourceWidth != 1); - - const T *src = (const T*)sourceData; - T *dst = (T*)destData; - - for (unsigned int x = 0; x < mipWidth; x++) - { - T::average(&dst[x], &src[x * 2], &src[x * 2 + 1]); - } - } - else if (sourceWidth == 1) - { - ASSERT(sourceHeight != 1); +inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); - for (unsigned int y = 0; y < mipHeight; y++) - { - const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch); - const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch); - T *dst = (T*)(destData + y * destPitch); - - T::average(dst, src0, src1); - } - } - else - { - for (unsigned int y = 0; y < mipHeight; y++) - { - const T *src0 = (const T*)(sourceData + y * 2 * sourcePitch); - const T *src1 = (const T*)(sourceData + y * 2 * sourcePitch + sourcePitch); - T *dst = (T*)(destData + y * destPitch); - - for (unsigned int x = 0; x < mipWidth; x++) - { - T tmp0; - T tmp1; - - T::average(&tmp0, &src0[x * 2], &src0[x * 2 + 1]); - T::average(&tmp1, &src1[x * 2], &src1[x * 2 + 1]); - T::average(&dst[x], &tmp0, &tmp1); - } - } - } -} } +#include "generatemip.inl" + #endif // LIBGLESV2_RENDERER_GENERATEMIP_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl b/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl new file mode 100644 index 0000000000..6788a42f03 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl @@ -0,0 +1,266 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// generatemip.inl: Defines the GenerateMip function, templated on the format +// type of the image for which mip levels are being generated. + +#include "common/mathutil.h" + +namespace rx +{ + +namespace priv +{ + +template +static inline T *GetPixel(uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch) +{ + return reinterpret_cast(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch)); +} + +template +static inline const T *GetPixel(const uint8_t *data, size_t x, size_t y, size_t z, size_t rowPitch, size_t depthPitch) +{ + return reinterpret_cast(data + (x * sizeof(T)) + (y * rowPitch) + (z * depthPitch)); +} + +template +static void GenerateMip_Y(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth == 1); + ASSERT(sourceHeight > 1); + ASSERT(sourceDepth == 1); + + for (size_t y = 0; y < destHeight; y++) + { + const T *src0 = GetPixel(sourceData, 0, y * 2, 0, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, 0, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, 0, y, 0, destRowPitch, destDepthPitch); + + T::average(dst, src0, src1); + } +} + +template +static void GenerateMip_X(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth > 1); + ASSERT(sourceHeight == 1); + ASSERT(sourceDepth == 1); + + for (size_t x = 0; x < destWidth; x++) + { + const T *src0 = GetPixel(sourceData, x * 2, 0, 0, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, x * 2 + 1, 0, 0, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, x, 0, 0, destRowPitch, destDepthPitch); + + T::average(dst, src0, src1); + } +} + +template +static void GenerateMip_Z(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth == 1); + ASSERT(sourceHeight == 1); + ASSERT(sourceDepth > 1); + + for (size_t z = 0; z < destDepth; z++) + { + const T *src0 = GetPixel(sourceData, 0, 0, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, 0, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, 0, 0, z, destRowPitch, destDepthPitch); + + T::average(dst, src0, src1); + } +} + +template +static void GenerateMip_XY(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth > 1); + ASSERT(sourceHeight > 1); + ASSERT(sourceDepth == 1); + + for (size_t y = 0; y < destHeight; y++) + { + for (size_t x = 0; x < destWidth; x++) + { + const T *src0 = GetPixel(sourceData, x * 2, y * 2, 0, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, x * 2, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); + const T *src2 = GetPixel(sourceData, x * 2 + 1, y * 2, 0, sourceRowPitch, sourceDepthPitch); + const T *src3 = GetPixel(sourceData, x * 2 + 1, y * 2 + 1, 0, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, x, y, 0, destRowPitch, destDepthPitch); + + T tmp0, tmp1; + + T::average(&tmp0, src0, src1); + T::average(&tmp1, src2, src3); + T::average(dst, &tmp0, &tmp1); + } + } +} + +template +static void GenerateMip_YZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth == 1); + ASSERT(sourceHeight > 1); + ASSERT(sourceDepth > 1); + + for (size_t z = 0; z < destDepth; z++) + { + for (size_t y = 0; y < destHeight; y++) + { + const T *src0 = GetPixel(sourceData, 0, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, 0, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src2 = GetPixel(sourceData, 0, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src3 = GetPixel(sourceData, 0, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, 0, y, z, destRowPitch, destDepthPitch); + + T tmp0, tmp1; + + T::average(&tmp0, src0, src1); + T::average(&tmp1, src2, src3); + T::average(dst, &tmp0, &tmp1); + } + } +} + +template +static void GenerateMip_XZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth > 1); + ASSERT(sourceHeight == 1); + ASSERT(sourceDepth > 1); + + for (size_t z = 0; z < destDepth; z++) + { + for (size_t x = 0; x < destWidth; x++) + { + const T *src0 = GetPixel(sourceData, x * 2, 0, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, x * 2, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src2 = GetPixel(sourceData, x * 2 + 1, 0, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src3 = GetPixel(sourceData, x * 2 + 1, 0, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, x, 0, z, destRowPitch, destDepthPitch); + + T tmp0, tmp1; + + T::average(&tmp0, src0, src1); + T::average(&tmp1, src2, src3); + T::average(dst, &tmp0, &tmp1); + } + } +} + +template +static void GenerateMip_XYZ(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + ASSERT(sourceWidth > 1); + ASSERT(sourceHeight > 1); + ASSERT(sourceDepth > 1); + + for (size_t z = 0; z < destDepth; z++) + { + for (size_t y = 0; y < destHeight; y++) + { + for (size_t x = 0; x < destWidth; x++) + { + const T *src0 = GetPixel(sourceData, x * 2, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src1 = GetPixel(sourceData, x * 2, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src2 = GetPixel(sourceData, x * 2, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src3 = GetPixel(sourceData, x * 2, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src4 = GetPixel(sourceData, x * 2 + 1, y * 2, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src5 = GetPixel(sourceData, x * 2 + 1, y * 2, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + const T *src6 = GetPixel(sourceData, x * 2 + 1, y * 2 + 1, z * 2, sourceRowPitch, sourceDepthPitch); + const T *src7 = GetPixel(sourceData, x * 2 + 1, y * 2 + 1, z * 2 + 1, sourceRowPitch, sourceDepthPitch); + T *dst = GetPixel(destData, x, y, z, destRowPitch, destDepthPitch); + + T tmp0, tmp1, tmp2, tmp3, tmp4, tmp5; + + T::average(&tmp0, src0, src1); + T::average(&tmp1, src2, src3); + T::average(&tmp2, src4, src5); + T::average(&tmp3, src6, src7); + + T::average(&tmp4, &tmp0, &tmp1); + T::average(&tmp5, &tmp2, &tmp3); + + T::average(dst, &tmp4, &tmp5); + } + } + } +} + + +typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + size_t destWidth, size_t destHeight, size_t destDepth, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch); + +template +static MipGenerationFunction GetMipGenerationFunction(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth) +{ + uint8_t index = ((sourceWidth > 1) ? 1 : 0) | + ((sourceHeight > 1) ? 2 : 0) | + ((sourceDepth > 1) ? 4 : 0); + + switch (index) + { + case 0: return NULL; + case 1: return GenerateMip_X; // W x 1 x 1 + case 2: return GenerateMip_Y; // 1 x H x 1 + case 3: return GenerateMip_XY; // W x H x 1 + case 4: return GenerateMip_Z; // 1 x 1 x D + case 5: return GenerateMip_XZ; // W x 1 x D + case 6: return GenerateMip_YZ; // 1 x H x D + case 7: return GenerateMip_XYZ; // W x H x D + } + + UNREACHABLE(); + return NULL; +} + +} + +template +inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth, + const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch, + uint8_t *destData, size_t destRowPitch, size_t destDepthPitch) +{ + size_t mipWidth = std::max(1, sourceWidth >> 1); + size_t mipHeight = std::max(1, sourceHeight >> 1); + size_t mipDepth = std::max(1, sourceDepth >> 1); + + priv::MipGenerationFunction generationFunction = priv::GetMipGenerationFunction(sourceWidth, sourceHeight, sourceDepth); + ASSERT(generationFunction != NULL); + + generationFunction(sourceWidth, sourceHeight, sourceDepth, sourceData, sourceRowPitch, sourceDepthPitch, + mipWidth, mipHeight, mipDepth, destData, destRowPitch, destDepthPitch); +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h b/src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h new file mode 100644 index 0000000000..2140a9ee72 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h @@ -0,0 +1,2029 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// imageformats.h: Defines image format types with functions for mip generation +// and copying. + +#ifndef LIBGLESV2_RENDERER_IMAGEFORMATS_H_ +#define LIBGLESV2_RENDERER_IMAGEFORMATS_H_ + +#include "common/mathutil.h" + +namespace rx +{ + +// Several structures share functionality for reading, writing or mipmapping but the layout +// must match the texture format which the structure represents. If collapsing or typedefing +// structs in this header, make sure the functionality and memory layout is exactly the same. + +struct L8 +{ + unsigned char L; + + static void readColor(gl::ColorF *dst, const L8 *src) + { + const float lum = gl::normalizedToFloat(src->L); + dst->red = lum; + dst->green = lum; + dst->blue = lum; + dst->alpha = 1.0f; + } + + static void writeColor(L8 *dst, const gl::ColorF *src) + { + dst->L = gl::floatToNormalized((src->red + src->green + src->blue) / 3.0f); + } + + static void average(L8 *dst, const L8 *src1, const L8 *src2) + { + dst->L = gl::average(src1->L, src2->L); + } +}; + +struct R8 +{ + unsigned char R; + + static void readColor(gl::ColorF *dst, const R8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R8 *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + } + + static void writeColor(R8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + } + + static void average(R8 *dst, const R8 *src1, const R8 *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct A8 +{ + unsigned char A; + + static void readColor(gl::ColorF *dst, const A8 *src) + { + dst->red = 0.0f; + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void writeColor(A8 *dst, const gl::ColorF *src) + { + dst->A = gl::floatToNormalized(src->alpha); + } + + static void average(A8 *dst, const A8 *src1, const A8 *src2) + { + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct L8A8 +{ + unsigned char L; + unsigned char A; + + static void readColor(gl::ColorF *dst, const L8A8 *src) + { + const float lum = gl::normalizedToFloat(src->L); + dst->red = lum; + dst->green = lum; + dst->blue = lum; + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void writeColor(L8A8 *dst, const gl::ColorF *src) + { + dst->L = gl::floatToNormalized((src->red + src->green + src->blue) / 3.0f); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void average(L8A8 *dst, const L8A8 *src1, const L8A8 *src2) + { + *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); + } +}; + +struct A8L8 +{ + unsigned char A; + unsigned char L; + + static void readColor(gl::ColorF *dst, const A8L8 *src) + { + const float lum = gl::normalizedToFloat(src->L); + dst->red = lum; + dst->green = lum; + dst->blue = lum; + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void writeColor(A8L8 *dst, const gl::ColorF *src) + { + dst->L = gl::floatToNormalized((src->red + src->green + src->blue) / 3.0f); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void average(A8L8 *dst, const A8L8 *src1, const A8L8 *src2) + { + *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); + } +}; + +struct R8G8 +{ + unsigned char R; + unsigned char G; + + static void readColor(gl::ColorF *dst, const R8G8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R8G8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R8G8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + } + + static void writeColor(R8G8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + } + + static void average(R8G8 *dst, const R8G8 *src1, const R8G8 *src2) + { + *(unsigned short*)dst = (((*(unsigned short*)src1 ^ *(unsigned short*)src2) & 0xFEFE) >> 1) + (*(unsigned short*)src1 & *(unsigned short*)src2); + } +}; + +struct R8G8B8 +{ + unsigned char R; + unsigned char G; + unsigned char B; + + static void readColor(gl::ColorF *dst, const R8G8B8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R8G8B8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->G; + dst->alpha = 1; + } + + static void writeColor(R8G8B8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + } + + static void writeColor(R8G8B8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + } + + static void average(R8G8B8 *dst, const R8G8B8 *src1, const R8G8B8 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct B8G8R8 +{ + unsigned char B; + unsigned char G; + unsigned char R; + + static void readColor(gl::ColorF *dst, const B8G8R8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const B8G8R8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->G; + dst->alpha = 1; + } + + static void writeColor(B8G8R8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + } + + static void writeColor(B8G8R8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + } + + static void average(B8G8R8 *dst, const B8G8R8 *src1, const B8G8R8 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R5G6B5 +{ + unsigned short RGB; + + static void readColor(gl::ColorF *dst, const R5G6B5 *src) + { + dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 11>(src->RGB)); + dst->green = gl::normalizedToFloat<6>(gl::getShiftedData<6, 5>(src->RGB)); + dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->RGB)); + dst->alpha = 1.0f; + } + + static void writeColor(R5G6B5 *dst, const gl::ColorF *src) + { + dst->RGB = gl::shiftData<5, 11>(gl::floatToNormalized<5, unsigned short>(src->red)) | + gl::shiftData<6, 5>(gl::floatToNormalized<6, unsigned short>(src->green)) | + gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue)); + } + + static void average(R5G6B5 *dst, const R5G6B5 *src1, const R5G6B5 *src2) + { + dst->RGB = gl::shiftData<5, 11>(gl::average(gl::getShiftedData<5, 11>(src1->RGB), gl::getShiftedData<5, 11>(src2->RGB))) | + gl::shiftData<6, 5>(gl::average(gl::getShiftedData<6, 5>(src1->RGB), gl::getShiftedData<6, 5>(src2->RGB))) | + gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->RGB), gl::getShiftedData<5, 0>(src2->RGB))); + } +}; + +struct A8R8G8B8 +{ + unsigned char A; + unsigned char R; + unsigned char G; + unsigned char B; + + static void readColor(gl::ColorF *dst, const A8R8G8B8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorUI *dst, const A8R8G8B8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(A8R8G8B8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void writeColor(A8R8G8B8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(A8R8G8B8 *dst, const A8R8G8B8 *src1, const A8R8G8B8 *src2) + { + *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); + } +}; + +struct R8G8B8A8 +{ + unsigned char R; + unsigned char G; + unsigned char B; + unsigned char A; + + static void readColor(gl::ColorF *dst, const R8G8B8A8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorUI *dst, const R8G8B8A8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R8G8B8A8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void writeColor(R8G8B8A8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(R8G8B8A8 *dst, const R8G8B8A8 *src1, const R8G8B8A8 *src2) + { + *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); + } +}; + +struct B8G8R8A8 +{ + unsigned char B; + unsigned char G; + unsigned char R; + unsigned char A; + + static void readColor(gl::ColorF *dst, const B8G8R8A8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorUI *dst, const B8G8R8A8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(B8G8R8A8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void writeColor(B8G8R8A8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(B8G8R8A8 *dst, const B8G8R8A8 *src1, const B8G8R8A8 *src2) + { + *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); + } +}; + +struct B8G8R8X8 +{ + unsigned char B; + unsigned char G; + unsigned char R; + unsigned char X; + + static void readColor(gl::ColorF *dst, const B8G8R8X8 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const B8G8R8X8 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(B8G8R8X8 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->X = 255; + } + + static void writeColor(B8G8R8X8 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->X = 255; + } + + static void average(B8G8R8X8 *dst, const B8G8R8X8 *src1, const B8G8R8X8 *src2) + { + *(unsigned int*)dst = (((*(unsigned int*)src1 ^ *(unsigned int*)src2) & 0xFEFEFEFE) >> 1) + (*(unsigned int*)src1 & *(unsigned int*)src2); + dst->X = 255; + } +}; + +struct B5G5R5A1 +{ + unsigned short BGRA; + + static void readColor(gl::ColorF *dst, const B5G5R5A1 *src) + { + dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->BGRA)); + dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->BGRA)); + dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->BGRA)); + dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->BGRA)); + } + + static void writeColor(B5G5R5A1 *dst, const gl::ColorF *src) + { + dst->BGRA = gl::shiftData<1, 15>(gl::floatToNormalized<1, unsigned short>(src->alpha)) | + gl::shiftData<5, 10>(gl::floatToNormalized<5, unsigned short>(src->red)) | + gl::shiftData<5, 5>(gl::floatToNormalized<5, unsigned short>(src->green)) | + gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->blue)); + } + + static void average(B5G5R5A1 *dst, const B5G5R5A1 *src1, const B5G5R5A1 *src2) + { + dst->BGRA = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->BGRA), gl::getShiftedData<1, 15>(src2->BGRA))) | + gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->BGRA), gl::getShiftedData<5, 10>(src2->BGRA))) | + gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->BGRA), gl::getShiftedData<5, 5>(src2->BGRA))) | + gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->BGRA), gl::getShiftedData<5, 0>(src2->BGRA))); + } +}; + +struct R5G5B5A1 +{ + unsigned short RGBA; + + static void readColor(gl::ColorF *dst, const R5G5B5A1 *src) + { + dst->alpha = gl::normalizedToFloat<1>(gl::getShiftedData<1, 15>(src->RGBA)); + dst->blue = gl::normalizedToFloat<5>(gl::getShiftedData<5, 10>(src->RGBA)); + dst->green = gl::normalizedToFloat<5>(gl::getShiftedData<5, 5>(src->RGBA)); + dst->red = gl::normalizedToFloat<5>(gl::getShiftedData<5, 0>(src->RGBA)); + } + + static void writeColor(R5G5B5A1 *dst, const gl::ColorF *src) + { + dst->RGBA = gl::shiftData<1, 15>(gl::floatToNormalized<1, unsigned short>(src->alpha)) | + gl::shiftData<5, 10>(gl::floatToNormalized<5, unsigned short>(src->blue)) | + gl::shiftData<5, 5>(gl::floatToNormalized<5, unsigned short>(src->green)) | + gl::shiftData<5, 0>(gl::floatToNormalized<5, unsigned short>(src->red)); + } + + static void average(R5G5B5A1 *dst, const R5G5B5A1 *src1, const R5G5B5A1 *src2) + { + dst->RGBA = gl::shiftData<1, 15>(gl::average(gl::getShiftedData<1, 15>(src1->RGBA), gl::getShiftedData<1, 15>(src2->RGBA))) | + gl::shiftData<5, 10>(gl::average(gl::getShiftedData<5, 10>(src1->RGBA), gl::getShiftedData<5, 10>(src2->RGBA))) | + gl::shiftData<5, 5>(gl::average(gl::getShiftedData<5, 5>(src1->RGBA), gl::getShiftedData<5, 5>(src2->RGBA))) | + gl::shiftData<5, 0>(gl::average(gl::getShiftedData<5, 0>(src1->RGBA), gl::getShiftedData<5, 0>(src2->RGBA))); + } +}; + +struct R4G4B4A4 +{ + unsigned char R : 4; + unsigned char G : 4; + unsigned char B : 4; + unsigned char A : 4; + + static void readColor(gl::ColorF *dst, const R4G4B4A4 *src) + { + dst->red = gl::normalizedToFloat<4>(src->R); + dst->green = gl::normalizedToFloat<4>(src->G); + dst->blue = gl::normalizedToFloat<4>(src->B); + dst->alpha = gl::normalizedToFloat<4>(src->A); + } + + static void writeColor(R4G4B4A4 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<4, unsigned char>(src->red); + dst->G = gl::floatToNormalized<4, unsigned char>(src->green); + dst->B = gl::floatToNormalized<4, unsigned char>(src->blue); + dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha); + } + + static void average(R4G4B4A4 *dst, const R4G4B4A4 *src1, const R4G4B4A4 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct A4R4G4B4 +{ + unsigned char A : 4; + unsigned char R : 4; + unsigned char G : 4; + unsigned char B : 4; + + static void readColor(gl::ColorF *dst, const A4R4G4B4 *src) + { + dst->red = gl::normalizedToFloat<4>(src->R); + dst->green = gl::normalizedToFloat<4>(src->G); + dst->blue = gl::normalizedToFloat<4>(src->B); + dst->alpha = gl::normalizedToFloat<4>(src->A); + } + + static void writeColor(A4R4G4B4 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<4, unsigned char>(src->red); + dst->G = gl::floatToNormalized<4, unsigned char>(src->green); + dst->B = gl::floatToNormalized<4, unsigned char>(src->blue); + dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha); + } + + static void average(A4R4G4B4 *dst, const A4R4G4B4 *src1, const A4R4G4B4 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct B4G4R4A4 +{ + unsigned char B : 4; + unsigned char G : 4; + unsigned char R : 4; + unsigned char A : 4; + + static void readColor(gl::ColorF *dst, const B4G4R4A4 *src) + { + dst->red = gl::normalizedToFloat<4>(src->R); + dst->green = gl::normalizedToFloat<4>(src->G); + dst->blue = gl::normalizedToFloat<4>(src->B); + dst->alpha = gl::normalizedToFloat<4>(src->A); + } + + static void writeColor(B4G4R4A4 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<4, unsigned char>(src->red); + dst->G = gl::floatToNormalized<4, unsigned char>(src->green); + dst->B = gl::floatToNormalized<4, unsigned char>(src->blue); + dst->A = gl::floatToNormalized<4, unsigned char>(src->alpha); + } + + static void average(B4G4R4A4 *dst, const B4G4R4A4 *src1, const B4G4R4A4 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R16 +{ + unsigned short R; + + static void readColor(gl::ColorF *dst, const R16 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R16 *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R16 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + } + + static void writeColor(R16 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + } + + static void average(R16 *dst, const R16 *src1, const R16 *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct R16G16 +{ + unsigned short R; + unsigned short G; + + static void readColor(gl::ColorF *dst, const R16G16 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R16G16 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R16G16 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + } + + static void writeColor(R16G16 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + } + + static void average(R16G16 *dst, const R16G16 *src1, const R16G16 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R16G16B16 +{ + unsigned short R; + unsigned short G; + unsigned short B; + + static void readColor(gl::ColorF *dst, const R16G16B16 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R16G16B16 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(R16G16B16 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + } + + static void writeColor(R16G16B16 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + } + + static void average(R16G16B16 *dst, const R16G16B16 *src1, const R16G16B16 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R16G16B16A16 +{ + unsigned short R; + unsigned short G; + unsigned short B; + unsigned short A; + + static void readColor(gl::ColorF *dst, const R16G16B16A16 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorUI *dst, const R16G16B16A16 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R16G16B16A16 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void writeColor(R16G16B16A16 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(R16G16B16A16 *dst, const R16G16B16A16 *src1, const R16G16B16A16 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R32 +{ + unsigned int R; + + static void readColor(gl::ColorF *dst, const R32 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R32 *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R32 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + } + + static void writeColor(R32 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + } + + static void average(R32 *dst, const R32 *src1, const R32 *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct R32G32 +{ + unsigned int R; + unsigned int G; + + static void readColor(gl::ColorF *dst, const R32G32 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R32G32 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R32G32 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + } + + static void writeColor(R32G32 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + } + + static void average(R32G32 *dst, const R32G32 *src1, const R32G32 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R32G32B32 +{ + unsigned int R; + unsigned int G; + unsigned int B; + + static void readColor(gl::ColorF *dst, const R32G32B32 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorUI *dst, const R32G32B32 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(R32G32B32 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + } + + static void writeColor(R32G32B32 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + } + + static void average(R32G32B32 *dst, const R32G32B32 *src1, const R32G32B32 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R32G32B32A32 +{ + unsigned int R; + unsigned int G; + unsigned int B; + unsigned int A; + + static void readColor(gl::ColorF *dst, const R32G32B32A32 *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorUI *dst, const R32G32B32A32 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R32G32B32A32 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void writeColor(R32G32B32A32 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(R32G32B32A32 *dst, const R32G32B32A32 *src1, const R32G32B32A32 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R8S +{ + char R; + + static void readColor(gl::ColorF *dst, const R8S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R8S *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R8S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + } + + static void writeColor(R8S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + } + + static void average(R8S *dst, const R8S *src1, const R8S *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct R8G8S +{ + char R; + char G; + + static void readColor(gl::ColorF *dst, const R8G8S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R8G8S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R8G8S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + } + + static void writeColor(R8G8S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + } + + static void average(R8G8S *dst, const R8G8S *src1, const R8G8S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R8G8B8S +{ + char R; + char G; + char B; + + static void readColor(gl::ColorF *dst, const R8G8B8S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R8G8B8S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(R8G8B8S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + } + + static void writeColor(R8G8B8S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + } + + static void average(R8G8B8S *dst, const R8G8B8S *src1, const R8G8B8S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R8G8B8A8S +{ + char R; + char G; + char B; + char A; + + static void readColor(gl::ColorF *dst, const R8G8B8A8S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorI *dst, const R8G8B8A8S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R8G8B8A8S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void writeColor(R8G8B8A8S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(R8G8B8A8S *dst, const R8G8B8A8S *src1, const R8G8B8A8S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R16S +{ + short R; + + static void readColor(gl::ColorF *dst, const R16S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R16S *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R16S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + } + + static void writeColor(R16S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + } + + static void average(R16S *dst, const R16S *src1, const R16S *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct R16G16S +{ + short R; + short G; + + static void readColor(gl::ColorF *dst, const R16G16S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R16G16S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R16G16S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + } + + static void writeColor(R16G16S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + } + + static void average(R16G16S *dst, const R16G16S *src1, const R16G16S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R16G16B16S +{ + short R; + short G; + short B; + + static void readColor(gl::ColorF *dst, const R16G16B16S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R16G16B16S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(R16G16B16S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + } + + static void writeColor(R16G16B16S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + } + + static void average(R16G16B16S *dst, const R16G16B16S *src1, const R16G16B16S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R16G16B16A16S +{ + short R; + short G; + short B; + short A; + + static void readColor(gl::ColorF *dst, const R16G16B16A16S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorI *dst, const R16G16B16A16S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R16G16B16A16S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void writeColor(R16G16B16A16S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(R16G16B16A16S *dst, const R16G16B16A16S *src1, const R16G16B16A16S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R32S +{ + int R; + + static void readColor(gl::ColorF *dst, const R32S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R32S *src) + { + dst->red = src->R; + dst->green = 0; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R32S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + } + + static void writeColor(R32S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + } + + static void average(R32S *dst, const R32S *src1, const R32S *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct R32G32S +{ + int R; + int G; + + static void readColor(gl::ColorF *dst, const R32G32S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R32G32S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0; + dst->alpha = 1; + } + + static void writeColor(R32G32S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + } + + static void writeColor(R32G32S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + } + + static void average(R32G32S *dst, const R32G32S *src1, const R32G32S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R32G32B32S +{ + int R; + int G; + int B; + + static void readColor(gl::ColorF *dst, const R32G32B32S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = 1.0f; + } + + static void readColor(gl::ColorI *dst, const R32G32B32S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1; + } + + static void writeColor(R32G32B32S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + } + + static void writeColor(R32G32B32S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + } + + static void average(R32G32B32S *dst, const R32G32B32S *src1, const R32G32B32S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R32G32B32A32S +{ + int R; + int G; + int B; + int A; + + static void readColor(gl::ColorF *dst, const R32G32B32A32S *src) + { + dst->red = gl::normalizedToFloat(src->R); + dst->green = gl::normalizedToFloat(src->G); + dst->blue = gl::normalizedToFloat(src->B); + dst->alpha = gl::normalizedToFloat(src->A); + } + + static void readColor(gl::ColorI *dst, const R32G32B32A32S *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R32G32B32A32S *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized(src->red); + dst->G = gl::floatToNormalized(src->green); + dst->B = gl::floatToNormalized(src->blue); + dst->A = gl::floatToNormalized(src->alpha); + } + + static void writeColor(R32G32B32A32S *dst, const gl::ColorI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(R32G32B32A32S *dst, const R32G32B32A32S *src1, const R32G32B32A32S *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct A16B16G16R16F +{ + unsigned short A; + unsigned short R; + unsigned short G; + unsigned short B; + + static void readColor(gl::ColorF *dst, const A16B16G16R16F *src) + { + dst->red = gl::float16ToFloat32(src->R); + dst->green = gl::float16ToFloat32(src->G); + dst->blue = gl::float16ToFloat32(src->B); + dst->alpha = gl::float16ToFloat32(src->A); + } + + static void writeColor(A16B16G16R16F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat16(src->red); + dst->G = gl::float32ToFloat16(src->green); + dst->B = gl::float32ToFloat16(src->blue); + dst->A = gl::float32ToFloat16(src->alpha); + } + + static void average(A16B16G16R16F *dst, const A16B16G16R16F *src1, const A16B16G16R16F *src2) + { + dst->R = gl::averageHalfFloat(src1->R, src2->R); + dst->G = gl::averageHalfFloat(src1->G, src2->G); + dst->B = gl::averageHalfFloat(src1->B, src2->B); + dst->A = gl::averageHalfFloat(src1->A, src2->A); + } +}; + +struct R16G16B16A16F +{ + unsigned short R; + unsigned short G; + unsigned short B; + unsigned short A; + + static void readColor(gl::ColorF *dst, const R16G16B16A16F *src) + { + dst->red = gl::float16ToFloat32(src->R); + dst->green = gl::float16ToFloat32(src->G); + dst->blue = gl::float16ToFloat32(src->B); + dst->alpha = gl::float16ToFloat32(src->A); + } + + static void writeColor(R16G16B16A16F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat16(src->red); + dst->G = gl::float32ToFloat16(src->green); + dst->B = gl::float32ToFloat16(src->blue); + dst->A = gl::float32ToFloat16(src->alpha); + } + + static void average(R16G16B16A16F *dst, const R16G16B16A16F *src1, const R16G16B16A16F *src2) + { + dst->R = gl::averageHalfFloat(src1->R, src2->R); + dst->G = gl::averageHalfFloat(src1->G, src2->G); + dst->B = gl::averageHalfFloat(src1->B, src2->B); + dst->A = gl::averageHalfFloat(src1->A, src2->A); + } +}; + +struct R16F +{ + unsigned short R; + + static void readColor(gl::ColorF *dst, const R16F *src) + { + dst->red = gl::float16ToFloat32(src->R); + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void writeColor(R16F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat16(src->red); + } + + static void average(R16F *dst, const R16F *src1, const R16F *src2) + { + dst->R = gl::averageHalfFloat(src1->R, src2->R); + } +}; + +struct A16F +{ + unsigned short A; + + static void readColor(gl::ColorF *dst, const A16F *src) + { + dst->red = 0.0f; + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = gl::float16ToFloat32(src->A); + } + + static void writeColor(A16F *dst, const gl::ColorF *src) + { + dst->A = gl::float32ToFloat16(src->alpha); + } + + static void average(A16F *dst, const A16F *src1, const A16F *src2) + { + dst->A = gl::averageHalfFloat(src1->A, src2->A); + } +}; + +struct L16F +{ + unsigned short L; + + static void readColor(gl::ColorF *dst, const L16F *src) + { + float lum = gl::float16ToFloat32(src->L); + dst->red = lum; + dst->green = lum; + dst->blue = lum; + dst->alpha = 1.0f; + } + + static void writeColor(L16F *dst, const gl::ColorF *src) + { + dst->L = gl::float32ToFloat16((src->red + src->green + src->blue) / 3.0f); + } + + static void average(L16F *dst, const L16F *src1, const L16F *src2) + { + dst->L = gl::averageHalfFloat(src1->L, src2->L); + } +}; + +struct L16A16F +{ + unsigned short L; + unsigned short A; + + static void readColor(gl::ColorF *dst, const L16A16F *src) + { + float lum = gl::float16ToFloat32(src->L); + dst->red = lum; + dst->green = lum; + dst->blue = lum; + dst->alpha = gl::float16ToFloat32(src->A); + } + + static void writeColor(L16A16F *dst, const gl::ColorF *src) + { + dst->L = gl::float32ToFloat16((src->red + src->green + src->blue) / 3.0f); + dst->A = gl::float32ToFloat16(src->alpha); + } + + static void average(L16A16F *dst, const L16A16F *src1, const L16A16F *src2) + { + dst->L = gl::averageHalfFloat(src1->L, src2->L); + dst->A = gl::averageHalfFloat(src1->A, src2->A); + } +}; + +struct R16G16F +{ + unsigned short R; + unsigned short G; + + static void readColor(gl::ColorF *dst, const R16G16F *src) + { + dst->red = gl::float16ToFloat32(src->R); + dst->green = gl::float16ToFloat32(src->G); + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void writeColor(R16G16F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat16(src->red); + dst->G = gl::float32ToFloat16(src->green); + } + + static void average(R16G16F *dst, const R16G16F *src1, const R16G16F *src2) + { + dst->R = gl::averageHalfFloat(src1->R, src2->R); + dst->G = gl::averageHalfFloat(src1->G, src2->G); + } +}; + +struct R16G16B16F +{ + unsigned short R; + unsigned short G; + unsigned short B; + + static void readColor(gl::ColorF *dst, const R16G16B16F *src) + { + dst->red = gl::float16ToFloat32(src->R); + dst->green = gl::float16ToFloat32(src->G); + dst->blue = gl::float16ToFloat32(src->B); + dst->alpha = 1.0f; + } + + static void writeColor(R16G16B16F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat16(src->red); + dst->G = gl::float32ToFloat16(src->green); + dst->B = gl::float32ToFloat16(src->blue); + } + + static void average(R16G16B16F *dst, const R16G16B16F *src1, const R16G16B16F *src2) + { + dst->R = gl::averageHalfFloat(src1->R, src2->R); + dst->G = gl::averageHalfFloat(src1->G, src2->G); + dst->B = gl::averageHalfFloat(src1->B, src2->B); + } +}; + +struct A32B32G32R32F +{ + float A; + float R; + float G; + float B; + + static void readColor(gl::ColorF *dst, const A32B32G32R32F *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(A32B32G32R32F *dst, const gl::ColorF *src) + { + dst->R = src->red; + dst->G = src->green; + dst->B = src->blue; + dst->A = src->alpha; + } + + static void average(A32B32G32R32F *dst, const A32B32G32R32F *src1, const A32B32G32R32F *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R32G32B32A32F +{ + float R; + float G; + float B; + float A; + + static void readColor(gl::ColorF *dst, const R32G32B32A32F *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R32G32B32A32F *dst, const gl::ColorF *src) + { + dst->R = src->red; + dst->G = src->green; + dst->B = src->blue; + dst->A = src->alpha; + } + + static void average(R32G32B32A32F *dst, const R32G32B32A32F *src1, const R32G32B32A32F *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R32F +{ + float R; + + static void readColor(gl::ColorF *dst, const R32F *src) + { + dst->red = src->R; + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void writeColor(R32F *dst, const gl::ColorF *src) + { + dst->R = src->red; + } + + static void average(R32F *dst, const R32F *src1, const R32F *src2) + { + dst->R = gl::average(src1->R, src2->R); + } +}; + +struct A32F +{ + float A; + + static void readColor(gl::ColorF *dst, const A32F *src) + { + dst->red = 0.0f; + dst->green = 0.0f; + dst->blue = 0.0f; + dst->alpha = src->A; + } + + static void writeColor(A32F *dst, const gl::ColorF *src) + { + dst->A = src->alpha; + } + + static void average(A32F *dst, const A32F *src1, const A32F *src2) + { + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct L32F +{ + float L; + + static void readColor(gl::ColorF *dst, const L32F *src) + { + dst->red = src->L; + dst->green = src->L; + dst->blue = src->L; + dst->alpha = 1.0f; + } + + static void writeColor(L32F *dst, const gl::ColorF *src) + { + dst->L = (src->red + src->green + src->blue) / 3.0f; + } + + static void average(L32F *dst, const L32F *src1, const L32F *src2) + { + dst->L = gl::average(src1->L, src2->L); + } +}; + +struct L32A32F +{ + float L; + float A; + + static void readColor(gl::ColorF *dst, const L32A32F *src) + { + dst->red = src->L; + dst->green = src->L; + dst->blue = src->L; + dst->alpha = src->A; + } + + static void writeColor(L32A32F *dst, const gl::ColorF *src) + { + dst->L = (src->red + src->green + src->blue) / 3.0f; + dst->A = src->alpha; + } + + static void average(L32A32F *dst, const L32A32F *src1, const L32A32F *src2) + { + dst->L = gl::average(src1->L, src2->L); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R32G32F +{ + float R; + float G; + + static void readColor(gl::ColorF *dst, const R32G32F *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = 0.0f; + dst->alpha = 1.0f; + } + + static void writeColor(R32G32F *dst, const gl::ColorF *src) + { + dst->R = src->red; + dst->G = src->green; + } + + static void average(R32G32F *dst, const R32G32F *src1, const R32G32F *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + } +}; + +struct R32G32B32F +{ + float R; + float G; + float B; + + static void readColor(gl::ColorF *dst, const R32G32B32F *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = 1.0f; + } + + static void writeColor(R32G32B32F *dst, const gl::ColorF *src) + { + dst->R = src->red; + dst->G = src->green; + dst->B = src->blue; + } + + static void average(R32G32B32F *dst, const R32G32B32F *src1, const R32G32B32F *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + } +}; + +struct R10G10B10A2 +{ + unsigned int R : 10; + unsigned int G : 10; + unsigned int B : 10; + unsigned int A : 2; + + static void readColor(gl::ColorF *dst, const R10G10B10A2 *src) + { + dst->red = gl::normalizedToFloat<10>(src->R); + dst->green = gl::normalizedToFloat<10>(src->G); + dst->blue = gl::normalizedToFloat<10>(src->B); + dst->alpha = gl::normalizedToFloat< 2>(src->A); + } + + static void readColor(gl::ColorUI *dst, const R10G10B10A2 *src) + { + dst->red = src->R; + dst->green = src->G; + dst->blue = src->B; + dst->alpha = src->A; + } + + static void writeColor(R10G10B10A2 *dst, const gl::ColorF *src) + { + dst->R = gl::floatToNormalized<10, unsigned int>(src->red); + dst->G = gl::floatToNormalized<10, unsigned int>(src->green); + dst->B = gl::floatToNormalized<10, unsigned int>(src->blue); + dst->A = gl::floatToNormalized< 2, unsigned int>(src->alpha); + } + + static void writeColor(R10G10B10A2 *dst, const gl::ColorUI *src) + { + dst->R = static_cast(src->red); + dst->G = static_cast(src->green); + dst->B = static_cast(src->blue); + dst->A = static_cast(src->alpha); + } + + static void average(R10G10B10A2 *dst, const R10G10B10A2 *src1, const R10G10B10A2 *src2) + { + dst->R = gl::average(src1->R, src2->R); + dst->G = gl::average(src1->G, src2->G); + dst->B = gl::average(src1->B, src2->B); + dst->A = gl::average(src1->A, src2->A); + } +}; + +struct R9G9B9E5 +{ + unsigned int R : 9; + unsigned int G : 9; + unsigned int B : 9; + unsigned int E : 5; + + static void readColor(gl::ColorF *dst, const R9G9B9E5 *src) + { + gl::convert999E5toRGBFloats(gl::bitCast(*src), &dst->red, &dst->green, &dst->blue); + dst->alpha = 1.0f; + } + + static void writeColor(R9G9B9E5 *dst, const gl::ColorF *src) + { + *reinterpret_cast(dst) = gl::convertRGBFloatsTo999E5(src->red, + src->green, + src->blue); + } + + static void average(R9G9B9E5 *dst, const R9G9B9E5 *src1, const R9G9B9E5 *src2) + { + float r1, g1, b1; + gl::convert999E5toRGBFloats(*reinterpret_cast(src1), &r1, &g1, &b1); + + float r2, g2, b2; + gl::convert999E5toRGBFloats(*reinterpret_cast(src2), &r2, &g2, &b2); + + *reinterpret_cast(dst) = gl::convertRGBFloatsTo999E5(gl::average(r1, r2), + gl::average(g1, g2), + gl::average(b1, b2)); + } +}; + +struct R11G11B10F +{ + unsigned int R : 11; + unsigned int G : 11; + unsigned int B : 10; + + static void readColor(gl::ColorF *dst, const R11G11B10F *src) + { + dst->red = gl::float11ToFloat32(src->R); + dst->green = gl::float11ToFloat32(src->G); + dst->blue = gl::float10ToFloat32(src->B); + dst->alpha = 1.0f; + } + + static void writeColor(R11G11B10F *dst, const gl::ColorF *src) + { + dst->R = gl::float32ToFloat11(src->red); + dst->G = gl::float32ToFloat11(src->green); + dst->B = gl::float32ToFloat10(src->blue); + } + + static void average(R11G11B10F *dst, const R11G11B10F *src1, const R11G11B10F *src2) + { + dst->R = gl::averageFloat11(src1->R, src2->R); + dst->G = gl::averageFloat11(src1->G, src2->G); + dst->B = gl::averageFloat10(src1->B, src2->B); + } +}; + +} + +#endif // LIBGLESV2_RENDERER_IMAGEFORMATS_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp new file mode 100644 index 0000000000..4a294608ae --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp @@ -0,0 +1,662 @@ +#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 +// found in the LICENSE file. +// + +// loadimage.cpp: Defines image loading functions. + +#include "libGLESv2/renderer/loadimage.h" + +namespace rx +{ + +void LoadA8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = static_cast(source[x]) << 24; + } + } + } +} + +void LoadA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + // Same as loading to RGBA + LoadA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); +} + +void LoadA32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + float *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = 0.0f; + dest[4 * x + 1] = 0.0f; + dest[4 * x + 2] = 0.0f; + dest[4 * x + 3] = source[x]; + } + } + } +} + +void LoadA16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = 0; + dest[4 * x + 1] = 0; + dest[4 * x + 2] = 0; + dest[4 * x + 3] = source[x]; + } + } + } +} + +void LoadL8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x]; + dest[4 * x + 1] = source[x]; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadL8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + // Same as loading to RGBA + LoadL8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); +} + +void LoadL32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + float *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x]; + dest[4 * x + 1] = source[x]; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = 1.0f; + } + } + } +} + +void LoadL16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x]; + dest[4 * x + 1] = source[x]; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = gl::Float16One; + } + } + } +} + +void LoadLA8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = source[2 * x + 0]; + dest[4 * x + 1] = source[2 * x + 0]; + dest[4 * x + 2] = source[2 * x + 0]; + dest[4 * x + 3] = source[2 * x + 1]; + } + } + } +} + +void LoadLA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + // Same as loading to RGBA + LoadLA8ToRGBA8(width, height, depth, input, inputRowPitch, inputDepthPitch, output, outputRowPitch, outputDepthPitch); +} + +void LoadLA32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + float *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = source[2 * x + 0]; + dest[4 * x + 1] = source[2 * x + 0]; + dest[4 * x + 2] = source[2 * x + 0]; + dest[4 * x + 3] = source[2 * x + 1]; + } + } + } +} + +void LoadLA16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = source[2 * x + 0]; + dest[4 * x + 1] = source[2 * x + 0]; + dest[4 * x + 2] = source[2 * x + 0]; + dest[4 * x + 3] = source[2 * x + 1]; + } + } + } +} + +void LoadRGB8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = source[x * 3 + 2]; + dest[4 * x + 1] = source[x * 3 + 1]; + dest[4 * x + 2] = source[x * 3 + 0]; + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadRG8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = 0x00; + dest[4 * x + 1] = source[x * 2 + 1]; + dest[4 * x + 2] = source[x * 2 + 0]; + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadR8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[4 * x + 0] = 0x00; + dest[4 * x + 1] = 0x00; + dest[4 * x + 2] = source[x]; + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadR5G6B5ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t rgb = source[x]; + dest[4 * x + 0] = ((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2); + dest[4 * x + 1] = ((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9); + dest[4 * x + 2] = ((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13); + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadR5G6B5ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t rgb = source[x]; + dest[4 * x + 0] = ((rgb & 0xF800) >> 8) | ((rgb & 0xF800) >> 13); + dest[4 * x + 1] = ((rgb & 0x07E0) >> 3) | ((rgb & 0x07E0) >> 9); + dest[4 * x + 2] = ((rgb & 0x001F) << 3) | ((rgb & 0x001F) >> 2); + dest[4 * x + 3] = 0xFF; + } + } + } +} + +void LoadRGBA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint32_t rgba = source[x]; + dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + } + } + } +} + +void LoadRGBA4ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); + dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); + dest[4 * x + 2] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); + dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); + } + } + } +} + +void LoadRGBA4ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0xF000) >> 8) | ((rgba & 0xF000) >> 12); + dest[4 * x + 1] = ((rgba & 0x0F00) >> 4) | ((rgba & 0x0F00) >> 8); + dest[4 * x + 2] = ((rgba & 0x00F0) << 0) | ((rgba & 0x00F0) >> 4); + dest[4 * x + 3] = ((rgba & 0x000F) << 4) | ((rgba & 0x000F) >> 0); + } + } + } +} + +void LoadBGRA4ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t bgra = source[x]; + dest[4 * x + 0] = ((bgra & 0xF000) >> 8) | ((bgra & 0xF000) >> 12); + dest[4 * x + 1] = ((bgra & 0x0F00) >> 4) | ((bgra & 0x0F00) >> 8); + dest[4 * x + 2] = ((bgra & 0x00F0) << 0) | ((bgra & 0x00F0) >> 4); + dest[4 * x + 3] = ((bgra & 0x000F) << 4) | ((bgra & 0x000F) >> 0); + } + } + } +} + +void LoadRGB5A1ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); + dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); + dest[4 * x + 2] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); + dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; + } + } + } +} + +void LoadRGB5A1ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t rgba = source[x]; + dest[4 * x + 0] = ((rgba & 0xF800) >> 8) | ((rgba & 0xF800) >> 13); + dest[4 * x + 1] = ((rgba & 0x07C0) >> 3) | ((rgba & 0x07C0) >> 8); + dest[4 * x + 2] = ((rgba & 0x003E) << 2) | ((rgba & 0x003E) >> 3); + dest[4 * x + 3] = (rgba & 0x0001) ? 0xFF : 0; + } + } + } +} + + +void LoadBGR5A1ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint16_t bgra = source[x]; + dest[4 * x + 0] = ((bgra & 0xF800) >> 8) | ((bgra & 0xF800) >> 13); + dest[4 * x + 1] = ((bgra & 0x07C0) >> 3) | ((bgra & 0x07C0) >> 8); + dest[4 * x + 2] = ((bgra & 0x003E) << 2) | ((bgra & 0x003E) >> 3); + dest[4 * x + 3] = (bgra & 0x0001) ? 0xFF : 0; + } + } + } +} + +void LoadRGB10A2ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint32_t rgba = source[x]; + dest[4 * x + 0] = (rgba & 0x000003FF) >> 2; + dest[4 * x + 1] = (rgba & 0x000FFC00) >> 12; + dest[4 * x + 2] = (rgba & 0x3FF00000) >> 22; + dest[4 * x + 3] = ((rgba & 0xC0000000) >> 30) * 0x55; + } + } + } +} + +void LoadRGB16FToRGB9E5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = gl::convertRGBFloatsTo999E5(gl::float16ToFloat32(source[x * 3 + 0]), + gl::float16ToFloat32(source[x * 3 + 1]), + gl::float16ToFloat32(source[x * 3 + 2])); + } + } + } +} + +void LoadRGB32FToRGB9E5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = gl::convertRGBFloatsTo999E5(source[x * 3 + 0], source[x * 3 + 1], source[x * 3 + 2]); + } + } + } +} + +void LoadRGB16FToRG11B10F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint16_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 0])) << 0) | + (gl::float32ToFloat11(gl::float16ToFloat32(source[x * 3 + 1])) << 11) | + (gl::float32ToFloat10(gl::float16ToFloat32(source[x * 3 + 2])) << 22); + } + } + } +} + +void LoadRGB32FToRG11B10F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = (gl::float32ToFloat11(source[x * 3 + 0]) << 0) | + (gl::float32ToFloat11(source[x * 3 + 1]) << 11) | + (gl::float32ToFloat10(source[x * 3 + 2]) << 22); + } + } + } +} + +void LoadG8R24ToR24G8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + uint32_t d = source[x] >> 8; + uint8_t s = source[x] & 0xFF; + dest[x] = d | (s << 24); + } + } + } +} + +void LoadRGB32FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x * 4 + 0] = gl::float32ToFloat16(source[x * 3 + 0]); + dest[x * 4 + 1] = gl::float32ToFloat16(source[x * 3 + 1]); + dest[x * 4 + 2] = gl::float32ToFloat16(source[x * 3 + 2]); + dest[x * 4 + 3] = gl::Float16One; + } + } + } +} + +void LoadR32ToR16(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x] = source[x] >> 16; + } + } + } +} + +void LoadR32ToR24G8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + + for (size_t x = 0; x < width; x++) + { + dest[x] = source[x] >> 8; + } + } + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h new file mode 100644 index 0000000000..bcdff24a66 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h @@ -0,0 +1,193 @@ +// +// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// loadimage.h: Defines image loading functions + +#ifndef LIBGLESV2_RENDERER_LOADIMAGE_H_ +#define LIBGLESV2_RENDERER_LOADIMAGE_H_ + +#include "libGLESv2/angletypes.h" + +#include + +namespace rx +{ + +void LoadA8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadA32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadA16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadL8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadL8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadL32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadL16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadLA8ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadLA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadLA32FToRGBA32F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadLA16FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRG8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR8ToBGRX8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR5G6B5ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR5G6B5ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGBA8ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGBA4ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGBA4ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadBGRA4ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB5A1ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB5A1ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadBGR5A1ToBGRA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB10A2ToRGBA8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB16FToRGB9E5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB32FToRGB9E5(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB16FToRG11B10F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB32FToRG11B10F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadG8R24ToR24G8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline void LoadToNative(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline void LoadToNative3To4(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline void Load32FTo16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadRGB32FToRGBA16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline void LoadCompressedToNative(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR32ToR16(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline void Initialize4ComponentData(size_t width, size_t height, size_t depth, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +void LoadR32ToR24G8(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch); + +template +inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch); + +template +inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch); + +} + +#include "loadimage.inl" + +#endif // LIBGLESV2_RENDERER_LOADIMAGE_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl new file mode 100644 index 0000000000..abd0a3673c --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl @@ -0,0 +1,156 @@ +// +// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "common/mathutil.h" + +namespace rx +{ + +template +inline T *OffsetDataPointer(uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch) +{ + return reinterpret_cast(data + (y * rowPitch) + (z * depthPitch)); +} + +template +inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_t rowPitch, size_t depthPitch) +{ + return reinterpret_cast(data + (y * rowPitch) + (z * depthPitch)); +} + +template +inline void LoadToNative(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + const size_t rowSize = width * sizeof(type) * componentCount; + const size_t layerSize = rowSize * height; + const size_t imageSize = layerSize * depth; + + if (layerSize == inputDepthPitch && layerSize == outputDepthPitch) + { + ASSERT(rowSize == inputRowPitch && rowSize == outputRowPitch); + memcpy(output, input, imageSize); + } + else if (rowSize == inputRowPitch && rowSize == outputRowPitch) + { + for (size_t z = 0; z < depth; z++) + { + const type *source = OffsetDataPointer(input, 0, z, inputRowPitch, inputDepthPitch); + type *dest = OffsetDataPointer(output, 0, z, outputRowPitch, outputDepthPitch); + + memcpy(dest, source, layerSize); + } + } + else + { + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const type *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + type *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + memcpy(dest, source, width * sizeof(type) * componentCount); + } + } + } +} + +template +inline void LoadToNative3To4(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + const type fourthValue = gl::bitCast(fourthComponentBits); + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const type *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + type *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + dest[x * 4 + 0] = source[x * 3 + 0]; + dest[x * 4 + 1] = source[x * 3 + 1]; + dest[x * 4 + 2] = source[x * 3 + 2]; + dest[x * 4 + 3] = fourthValue; + } + } + } +} + +template +inline void Load32FTo16F(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + const size_t elementWidth = componentCount * width; + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const float *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint16_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + + for (size_t x = 0; x < elementWidth; x++) + { + dest[x] = gl::float32ToFloat16(source[x]); + } + } + } +} + +template +inline void LoadCompressedToNative(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + const size_t columns = (width + (blockWidth - 1)) / blockWidth; + const size_t rows = (height + (blockHeight - 1)) / blockHeight; + + for (size_t z = 0; z < depth; ++z) + { + for (size_t y = 0; y < rows; ++y) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint8_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + memcpy(dest, source, columns * blockSize); + } + } +} + +template +inline void Initialize4ComponentData(size_t width, size_t height, size_t depth, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ + type writeValues[4] = + { + gl::bitCast(firstBits), + gl::bitCast(secondBits), + gl::bitCast(thirdBits), + gl::bitCast(fourthBits), + }; + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + type *destRow = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + for (size_t x = 0; x < width; x++) + { + type* destPixel = destRow + x * 4; + + // This could potentially be optimized by generating an entire row of initialization + // data and copying row by row instead of pixel by pixel. + memcpy(destPixel, writeValues, sizeof(type) * 4); + } + } + } +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp new file mode 100644 index 0000000000..dcf347d421 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp @@ -0,0 +1,113 @@ +#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 +// found in the LICENSE file. +// + +// loadimageSSE2.cpp: Defines image loading functions. It's +// in a separated file for GCC, which can enable SSE usage only per-file, +// not for code blocks that use SSE2 explicitly. + +#include "libGLESv2/renderer/loadimage.h" + +#if !defined(__SSE2__) && (defined(_M_X64) || _M_IX86_FP == 2) +#define __SSE2__ +#endif + +namespace rx +{ + +void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ +#ifdef __SSE2__ + __m128i zeroWide = _mm_setzero_si128(); + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint8_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + + size_t x = 0; + + // Make output writes aligned + for (; ((reinterpret_cast(&dest[x]) & 0xF) != 0 && x < width); x++) + { + dest[x] = static_cast(source[x]) << 24; + } + + for (; x + 7 < width; x += 8) + { + __m128i sourceData = _mm_loadl_epi64(reinterpret_cast(&source[x])); + // Interleave each byte to 16bit, make the lower byte to zero + sourceData = _mm_unpacklo_epi8(zeroWide, sourceData); + // Interleave each 16bit to 32bit, make the lower 16bit to zero + __m128i lo = _mm_unpacklo_epi16(zeroWide, sourceData); + __m128i hi = _mm_unpackhi_epi16(zeroWide, sourceData); + + _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), lo); + _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x + 4]), hi); + } + + // Handle the remainder + for (; x < width; x++) + { + dest[x] = static_cast(source[x]) << 24; + } + } + } +#endif +} + +void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth, + const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch, + uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch) +{ +#ifdef __SSE2__ + __m128i brMask = _mm_set1_epi32(0x00ff00ff); + + for (size_t z = 0; z < depth; z++) + { + for (size_t y = 0; y < height; y++) + { + const uint32_t *source = OffsetDataPointer(input, y, z, inputRowPitch, inputDepthPitch); + uint32_t *dest = OffsetDataPointer(output, y, z, outputRowPitch, outputDepthPitch); + + size_t x = 0; + + // Make output writes aligned + for (; ((reinterpret_cast(&dest[x]) & 15) != 0) && x < width; x++) + { + uint32_t rgba = source[x]; + dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + } + + for (; x + 3 < width; x += 4) + { + __m128i sourceData = _mm_loadu_si128(reinterpret_cast(&source[x])); + // Mask out g and a, which don't change + __m128i gaComponents = _mm_andnot_si128(brMask, sourceData); + // Mask out b and r + __m128i brComponents = _mm_and_si128(sourceData, brMask); + // Swap b and r + __m128i brSwapped = _mm_shufflehi_epi16(_mm_shufflelo_epi16(brComponents, _MM_SHUFFLE(2, 3, 0, 1)), _MM_SHUFFLE(2, 3, 0, 1)); + __m128i result = _mm_or_si128(gaComponents, brSwapped); + _mm_store_si128(reinterpret_cast<__m128i*>(&dest[x]), result); + } + + // Perform leftover writes + for (; x < width; x++) + { + uint32_t rgba = source[x]; + dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00); + } + } + } +#endif +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h b/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h new file mode 100644 index 0000000000..590b9d48a3 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h @@ -0,0 +1,203 @@ +// +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// vertexconversion.h: A library of vertex conversion classes that can be used to build +// the FormatConverter objects used by the buffer conversion system. + +#ifndef LIBGLESV2_VERTEXCONVERSION_H_ +#define LIBGLESV2_VERTEXCONVERSION_H_ + +namespace rx +{ + +// Conversion types: +// static const bool identity: true if this is an identity transform, false otherwise +// static U convert(T): convert a single element from the input type to the output type +// typedef ... OutputType: the type produced by this conversion + +template +struct Identity +{ + static const bool identity = true; + + typedef T OutputType; + + static T convert(T x) + { + return x; + } +}; + +template +struct Cast +{ + static const bool identity = false; + + typedef ToT OutputType; + + static ToT convert(FromT x) + { + return static_cast(x); + } +}; + +template +struct Cast +{ + static const bool identity = true; + + typedef T OutputType; + + static T convert(T x) + { + return static_cast(x); + } +}; + +template +struct Normalize +{ + static const bool identity = false; + + typedef float OutputType; + + static float convert(T x) + { + typedef std::numeric_limits NL; + float f = static_cast(x); + + if (NL::is_signed) + { + // const float => VC2008 computes it at compile time + // static const float => VC2008 computes it the first time we get here, stores it to memory with static guard and all that. + const float divisor = 1.0f/(2*static_cast(NL::max())+1); + return (2*f+1)*divisor; + } + else + { + return f/NL::max(); + } + } +}; + +template +struct FixedToFloat +{ + static const bool identity = false; + + typedef float OutputType; + + static float convert(FromType x) + { + const float divisor = 1.0f / static_cast(static_cast(1) << ScaleBits); + return static_cast(x) * divisor; + } +}; + +// Widen types: +// static const unsigned int initialWidth: number of components before conversion +// static const unsigned int finalWidth: number of components after conversion + +// Float is supported at any size. +template +struct NoWiden +{ + static const std::size_t initialWidth = N; + static const std::size_t finalWidth = N; +}; + +// SHORT, norm-SHORT, norm-UNSIGNED_SHORT are supported but only with 2 or 4 components +template +struct WidenToEven +{ + static const std::size_t initialWidth = N; + static const std::size_t finalWidth = N+(N&1); +}; + +template +struct WidenToFour +{ + static const std::size_t initialWidth = N; + static const std::size_t finalWidth = 4; +}; + +// Most types have 0 and 1 that are just that. +template +struct SimpleDefaultValues +{ + static T zero() { return static_cast(0); } + static T one() { return static_cast(1); } +}; + +// But normalised types only store [0,1] or [-1,1] so 1.0 is represented by the max value. +template +struct NormalizedDefaultValues +{ + static T zero() { return static_cast(0); } + static T one() { return std::numeric_limits::max(); } +}; + +// Converter: +// static const bool identity: true if this is an identity transform (with no widening) +// static const std::size_t finalSize: number of bytes per output vertex +// static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out): convert an array of vertices. Input may be strided, but output will be unstrided. + +template > +struct VertexDataConverter +{ + typedef typename Converter::OutputType OutputType; + typedef InT InputType; + + static const bool identity = (WidenRule::initialWidth == WidenRule::finalWidth) && Converter::identity; + static const std::size_t finalSize = WidenRule::finalWidth * sizeof(OutputType); + + static void convertArray(const InputType *in, std::size_t stride, std::size_t n, OutputType *out) + { + for (std::size_t i = 0; i < n; i++) + { + const InputType *ein = pointerAddBytes(in, i * stride); + + copyComponent(out, ein, 0, static_cast(DefaultValueRule::zero())); + copyComponent(out, ein, 1, static_cast(DefaultValueRule::zero())); + copyComponent(out, ein, 2, static_cast(DefaultValueRule::zero())); + copyComponent(out, ein, 3, static_cast(DefaultValueRule::one())); + + out += WidenRule::finalWidth; + } + } + + static void convertArray(const void *in, std::size_t stride, std::size_t n, void *out) + { + return convertArray(static_cast(in), stride, n, static_cast(out)); + } + + private: + // Advance the given pointer by a number of bytes (not pointed-to elements). + template + static T *pointerAddBytes(T *basePtr, std::size_t numBytes) + { + return reinterpret_cast(reinterpret_cast(basePtr) + numBytes); + } + + static void copyComponent(OutputType *out, const InputType *in, std::size_t elementindex, OutputType defaultvalue) + { + if (WidenRule::finalWidth > elementindex) + { + if (WidenRule::initialWidth > elementindex) + { + out[elementindex] = Converter::convert(in[elementindex]); + } + else + { + out[elementindex] = defaultvalue; + } + } + } +}; + +} + +#endif // LIBGLESV2_VERTEXCONVERSION_H_ diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.cpp b/src/3rdparty/angle/src/libGLESv2/utilities.cpp deleted file mode 100644 index 30765ffba0..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/utilities.cpp +++ /dev/null @@ -1,817 +0,0 @@ -#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. -// - -// utilities.cpp: Conversion functions and other utility routines. - -#include "libGLESv2/utilities.h" -#include "libGLESv2/mathutil.h" -#if defined(ANGLE_OS_WINRT) -# include -# include -# include -# include - using namespace Microsoft::WRL; - using namespace ABI::Windows::Storage; -#endif - -namespace gl -{ - -int UniformComponentCount(GLenum type) -{ - switch (type) - { - case GL_BOOL: - case GL_FLOAT: - case GL_INT: - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - return 1; - case GL_BOOL_VEC2: - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - return 2; - case GL_INT_VEC3: - case GL_FLOAT_VEC3: - case GL_BOOL_VEC3: - return 3; - case GL_BOOL_VEC4: - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - case GL_FLOAT_MAT2: - return 4; - case GL_FLOAT_MAT3: - return 9; - case GL_FLOAT_MAT4: - return 16; - default: - UNREACHABLE(); - } - - return 0; -} - -GLenum UniformComponentType(GLenum type) -{ - switch(type) - { - case GL_BOOL: - case GL_BOOL_VEC2: - case GL_BOOL_VEC3: - case GL_BOOL_VEC4: - return GL_BOOL; - case GL_FLOAT: - case GL_FLOAT_VEC2: - case GL_FLOAT_VEC3: - case GL_FLOAT_VEC4: - case GL_FLOAT_MAT2: - case GL_FLOAT_MAT3: - case GL_FLOAT_MAT4: - return GL_FLOAT; - case GL_INT: - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_INT_VEC4: - return GL_INT; - default: - UNREACHABLE(); - } - - return GL_NONE; -} - -size_t UniformComponentSize(GLenum type) -{ - switch(type) - { - case GL_BOOL: return sizeof(GLint); - case GL_FLOAT: return sizeof(GLfloat); - case GL_INT: return sizeof(GLint); - default: UNREACHABLE(); - } - - return 0; -} - -size_t UniformInternalSize(GLenum type) -{ - // Expanded to 4-element vectors - return UniformComponentSize(UniformComponentType(type)) * VariableRowCount(type) * 4; -} - -size_t UniformExternalSize(GLenum type) -{ - return UniformComponentSize(UniformComponentType(type)) * UniformComponentCount(type); -} - -int VariableRowCount(GLenum type) -{ - switch (type) - { - case GL_NONE: - return 0; - case GL_BOOL: - case GL_FLOAT: - case GL_INT: - case GL_BOOL_VEC2: - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - case GL_INT_VEC3: - case GL_FLOAT_VEC3: - case GL_BOOL_VEC3: - case GL_BOOL_VEC4: - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - return 1; - case GL_FLOAT_MAT2: - return 2; - case GL_FLOAT_MAT3: - return 3; - case GL_FLOAT_MAT4: - return 4; - default: - UNREACHABLE(); - } - - return 0; -} - -int VariableColumnCount(GLenum type) -{ - switch (type) - { - case GL_NONE: - return 0; - case GL_BOOL: - case GL_FLOAT: - case GL_INT: - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - return 1; - case GL_BOOL_VEC2: - case GL_FLOAT_VEC2: - case GL_INT_VEC2: - case GL_FLOAT_MAT2: - return 2; - case GL_INT_VEC3: - case GL_FLOAT_VEC3: - case GL_BOOL_VEC3: - case GL_FLOAT_MAT3: - return 3; - case GL_BOOL_VEC4: - case GL_FLOAT_VEC4: - case GL_INT_VEC4: - case GL_FLOAT_MAT4: - return 4; - default: - UNREACHABLE(); - } - - return 0; -} - -int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize) -{ - ASSERT(allocationSize <= bitsSize); - - unsigned int mask = std::numeric_limits::max() >> (std::numeric_limits::digits - allocationSize); - - for (unsigned int i = 0; i < bitsSize - allocationSize + 1; i++) - { - if ((*bits & mask) == 0) - { - *bits |= mask; - return i; - } - - mask <<= 1; - } - - return -1; -} - -GLsizei ComputePitch(GLsizei width, GLint internalformat, GLint alignment) -{ - ASSERT(alignment > 0 && isPow2(alignment)); - - GLsizei rawPitch = ComputePixelSize(internalformat) * width; - return (rawPitch + alignment - 1) & ~(alignment - 1); -} - -GLsizei ComputeCompressedPitch(GLsizei width, GLenum internalformat) -{ - return ComputeCompressedSize(width, 1, internalformat); -} - -GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum internalformat) -{ - switch (internalformat) - { - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: - return 8 * ((width + 3) / 4) * ((height + 3) / 4); - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: - return 16 * ((width + 3) / 4) * ((height + 3) / 4); - default: - return 0; - } -} - -GLsizei ComputeTypeSize(GLenum type) -{ - switch (type) - { - case GL_BYTE: return 1; - case GL_UNSIGNED_BYTE: return 1; - case GL_SHORT: return 2; - case GL_UNSIGNED_SHORT: return 2; - case GL_INT: return 4; - case GL_UNSIGNED_INT: return 4; - case GL_FLOAT: return 4; - case GL_HALF_FLOAT_OES: return 2; - case GL_UNSIGNED_SHORT_5_6_5: return 2; - case GL_UNSIGNED_SHORT_4_4_4_4: return 2; - case GL_UNSIGNED_SHORT_5_5_5_1: return 2; - case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: return 2; - case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: return 2; - case GL_UNSIGNED_INT_2_10_10_10_REV_EXT: return 4; - case GL_UNSIGNED_INT_24_8_OES: return 4; - default: UNREACHABLE(); return 0; - } -} - -bool IsCompressed(GLenum format) -{ - if(format == GL_COMPRESSED_RGB_S3TC_DXT1_EXT || - format == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT || - format == GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE || - format == GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE) - { - return true; - } - else - { - return false; - } -} - -bool IsDepthTexture(GLenum format) -{ - if (format == GL_DEPTH_COMPONENT || - format == GL_DEPTH_STENCIL_OES || - format == GL_DEPTH_COMPONENT16 || - format == GL_DEPTH_COMPONENT32_OES || - format == GL_DEPTH24_STENCIL8_OES) - { - return true; - } - - return false; -} - -bool IsStencilTexture(GLenum format) -{ - if (format == GL_DEPTH_STENCIL_OES || - format == GL_DEPTH24_STENCIL8_OES) - { - return true; - } - - return false; -} - -void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset) -{ - int upsampleCount = 0; - - if (isCompressed) - { - // Don't expand the size of full textures that are at least 4x4 - // already. - if (isImage || *requestWidth < 4 || *requestHeight < 4) - { - while (*requestWidth % 4 != 0 || *requestHeight % 4 != 0) - { - *requestWidth <<= 1; - *requestHeight <<= 1; - upsampleCount++; - } - } - } - *levelOffset = upsampleCount; -} - -// Returns the size, in bytes, of a single texel in an Image -int ComputePixelSize(GLint internalformat) -{ - switch (internalformat) - { - case GL_ALPHA8_EXT: return sizeof(unsigned char); - case GL_LUMINANCE8_EXT: return sizeof(unsigned char); - case GL_ALPHA32F_EXT: return sizeof(float); - case GL_LUMINANCE32F_EXT: return sizeof(float); - case GL_ALPHA16F_EXT: return sizeof(unsigned short); - case GL_LUMINANCE16F_EXT: return sizeof(unsigned short); - case GL_LUMINANCE8_ALPHA8_EXT: return sizeof(unsigned char) * 2; - case GL_LUMINANCE_ALPHA32F_EXT: return sizeof(float) * 2; - case GL_LUMINANCE_ALPHA16F_EXT: return sizeof(unsigned short) * 2; - case GL_RGB8_OES: return sizeof(unsigned char) * 3; - case GL_RGB565: return sizeof(unsigned short); - case GL_RGB32F_EXT: return sizeof(float) * 3; - case GL_RGB16F_EXT: return sizeof(unsigned short) * 3; - case GL_RGBA8_OES: return sizeof(unsigned char) * 4; - case GL_RGBA4: return sizeof(unsigned short); - case GL_RGB5_A1: return sizeof(unsigned short); - case GL_RGBA32F_EXT: return sizeof(float) * 4; - case GL_RGBA16F_EXT: return sizeof(unsigned short) * 4; - case GL_BGRA8_EXT: return sizeof(unsigned char) * 4; - case GL_BGRA4_ANGLEX: return sizeof(unsigned short); - case GL_BGR5_A1_ANGLEX: return sizeof(unsigned short); - default: UNREACHABLE(); - } - - return 0; -} - -bool IsCubemapTextureTarget(GLenum target) -{ - return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z); -} - -bool IsInternalTextureTarget(GLenum target) -{ - return target == GL_TEXTURE_2D || IsCubemapTextureTarget(target); -} - -GLint ConvertSizedInternalFormat(GLenum format, GLenum type) -{ - switch (format) - { - case GL_ALPHA: - switch (type) - { - case GL_UNSIGNED_BYTE: return GL_ALPHA8_EXT; - case GL_FLOAT: return GL_ALPHA32F_EXT; - case GL_HALF_FLOAT_OES: return GL_ALPHA16F_EXT; - default: UNIMPLEMENTED(); - } - break; - case GL_LUMINANCE: - switch (type) - { - case GL_UNSIGNED_BYTE: return GL_LUMINANCE8_EXT; - case GL_FLOAT: return GL_LUMINANCE32F_EXT; - case GL_HALF_FLOAT_OES: return GL_LUMINANCE16F_EXT; - default: UNIMPLEMENTED(); - } - break; - case GL_LUMINANCE_ALPHA: - switch (type) - { - case GL_UNSIGNED_BYTE: return GL_LUMINANCE8_ALPHA8_EXT; - case GL_FLOAT: return GL_LUMINANCE_ALPHA32F_EXT; - case GL_HALF_FLOAT_OES: return GL_LUMINANCE_ALPHA16F_EXT; - default: UNIMPLEMENTED(); - } - break; - case GL_RGB: - switch (type) - { - case GL_UNSIGNED_BYTE: return GL_RGB8_OES; - case GL_UNSIGNED_SHORT_5_6_5: return GL_RGB565; - case GL_FLOAT: return GL_RGB32F_EXT; - case GL_HALF_FLOAT_OES: return GL_RGB16F_EXT; - default: UNIMPLEMENTED(); - } - break; - case GL_RGBA: - switch (type) - { - case GL_UNSIGNED_BYTE: return GL_RGBA8_OES; - case GL_UNSIGNED_SHORT_4_4_4_4: return GL_RGBA4; - case GL_UNSIGNED_SHORT_5_5_5_1: return GL_RGB5_A1; - case GL_FLOAT: return GL_RGBA32F_EXT; - case GL_HALF_FLOAT_OES: return GL_RGBA16F_EXT; - break; - default: UNIMPLEMENTED(); - } - break; - case GL_BGRA_EXT: - switch (type) - { - case GL_UNSIGNED_BYTE: return GL_BGRA8_EXT; - case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: return GL_BGRA4_ANGLEX; - case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: return GL_BGR5_A1_ANGLEX; - default: UNIMPLEMENTED(); - } - 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 format; - case GL_DEPTH_COMPONENT: - switch (type) - { - case GL_UNSIGNED_SHORT: return GL_DEPTH_COMPONENT16; - case GL_UNSIGNED_INT: return GL_DEPTH_COMPONENT32_OES; - default: UNIMPLEMENTED(); - } - break; - case GL_DEPTH_STENCIL_OES: - switch (type) - { - case GL_UNSIGNED_INT_24_8_OES: return GL_DEPTH24_STENCIL8_OES; - default: UNIMPLEMENTED(); - } - break; - default: - UNIMPLEMENTED(); - } - - return GL_NONE; -} - -GLenum ExtractFormat(GLenum internalformat) -{ - switch (internalformat) - { - case GL_RGB565: return GL_RGB; - case GL_RGBA4: return GL_RGBA; - case GL_RGB5_A1: return GL_RGBA; - case GL_RGB8_OES: return GL_RGB; - case GL_RGBA8_OES: return GL_RGBA; - case GL_LUMINANCE8_ALPHA8_EXT: return GL_LUMINANCE_ALPHA; - case GL_LUMINANCE8_EXT: return GL_LUMINANCE; - case GL_ALPHA8_EXT: return GL_ALPHA; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE; - case GL_RGBA32F_EXT: return GL_RGBA; - case GL_RGB32F_EXT: return GL_RGB; - case GL_ALPHA32F_EXT: return GL_ALPHA; - case GL_LUMINANCE32F_EXT: return GL_LUMINANCE; - case GL_LUMINANCE_ALPHA32F_EXT: return GL_LUMINANCE_ALPHA; - case GL_RGBA16F_EXT: return GL_RGBA; - case GL_RGB16F_EXT: return GL_RGB; - case GL_ALPHA16F_EXT: return GL_ALPHA; - case GL_LUMINANCE16F_EXT: return GL_LUMINANCE; - case GL_LUMINANCE_ALPHA16F_EXT: return GL_LUMINANCE_ALPHA; - case GL_BGRA8_EXT: return GL_BGRA_EXT; - case GL_DEPTH_COMPONENT16: return GL_DEPTH_COMPONENT; - case GL_DEPTH_COMPONENT32_OES: return GL_DEPTH_COMPONENT; - case GL_DEPTH24_STENCIL8_OES: return GL_DEPTH_STENCIL_OES; - default: return GL_NONE; // Unsupported - } -} - -GLenum ExtractType(GLenum internalformat) -{ - switch (internalformat) - { - case GL_RGB565: return GL_UNSIGNED_SHORT_5_6_5; - case GL_RGBA4: return GL_UNSIGNED_SHORT_4_4_4_4; - case GL_RGB5_A1: return GL_UNSIGNED_SHORT_5_5_5_1; - case GL_RGB8_OES: return GL_UNSIGNED_BYTE; - case GL_RGBA8_OES: return GL_UNSIGNED_BYTE; - case GL_LUMINANCE8_ALPHA8_EXT: return GL_UNSIGNED_BYTE; - case GL_LUMINANCE8_EXT: return GL_UNSIGNED_BYTE; - case GL_ALPHA8_EXT: return GL_UNSIGNED_BYTE; - case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: return GL_UNSIGNED_BYTE; - case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: return GL_UNSIGNED_BYTE; - case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: return GL_UNSIGNED_BYTE; - case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: return GL_UNSIGNED_BYTE; - case GL_RGBA32F_EXT: return GL_FLOAT; - case GL_RGB32F_EXT: return GL_FLOAT; - case GL_ALPHA32F_EXT: return GL_FLOAT; - case GL_LUMINANCE32F_EXT: return GL_FLOAT; - case GL_LUMINANCE_ALPHA32F_EXT: return GL_FLOAT; - case GL_RGBA16F_EXT: return GL_HALF_FLOAT_OES; - case GL_RGB16F_EXT: return GL_HALF_FLOAT_OES; - case GL_ALPHA16F_EXT: return GL_HALF_FLOAT_OES; - case GL_LUMINANCE16F_EXT: return GL_HALF_FLOAT_OES; - case GL_LUMINANCE_ALPHA16F_EXT: return GL_HALF_FLOAT_OES; - case GL_BGRA8_EXT: return GL_UNSIGNED_BYTE; - case GL_DEPTH_COMPONENT16: return GL_UNSIGNED_SHORT; - case GL_DEPTH_COMPONENT32_OES: return GL_UNSIGNED_INT; - case GL_DEPTH24_STENCIL8_OES: return GL_UNSIGNED_INT_24_8_OES; - default: return GL_NONE; // Unsupported - } -} - -bool IsColorRenderable(GLenum internalformat) -{ - switch (internalformat) - { - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGB565: - case GL_RGB8_OES: - case GL_RGBA8_OES: - return true; - case GL_DEPTH_COMPONENT16: - case GL_STENCIL_INDEX8: - case GL_DEPTH24_STENCIL8_OES: - return false; - case GL_BGRA8_EXT: - return true; - default: - UNIMPLEMENTED(); - } - - return false; -} - -bool IsDepthRenderable(GLenum internalformat) -{ - switch (internalformat) - { - case GL_DEPTH_COMPONENT16: - case GL_DEPTH24_STENCIL8_OES: - return true; - case GL_STENCIL_INDEX8: - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGB565: - case GL_RGB8_OES: - case GL_RGBA8_OES: - return false; - default: - UNIMPLEMENTED(); - } - - return false; -} - -bool IsStencilRenderable(GLenum internalformat) -{ - switch (internalformat) - { - case GL_STENCIL_INDEX8: - case GL_DEPTH24_STENCIL8_OES: - return true; - case GL_RGBA4: - case GL_RGB5_A1: - case GL_RGB565: - case GL_RGB8_OES: - case GL_RGBA8_OES: - case GL_DEPTH_COMPONENT16: - return false; - default: - UNIMPLEMENTED(); - } - - return false; -} - -bool IsFloat32Format(GLint internalformat) -{ - switch (internalformat) - { - case GL_RGBA32F_EXT: - case GL_RGB32F_EXT: - case GL_ALPHA32F_EXT: - case GL_LUMINANCE32F_EXT: - case GL_LUMINANCE_ALPHA32F_EXT: - return true; - default: - return false; - } -} - -bool IsFloat16Format(GLint internalformat) -{ - switch (internalformat) - { - case GL_RGBA16F_EXT: - case GL_RGB16F_EXT: - case GL_ALPHA16F_EXT: - case GL_LUMINANCE16F_EXT: - case GL_LUMINANCE_ALPHA16F_EXT: - return true; - default: - return false; - } -} - -unsigned int GetAlphaSize(GLenum colorFormat) -{ - switch (colorFormat) - { - case GL_RGBA16F_EXT: - return 16; - case GL_RGBA32F_EXT: - return 32; - case GL_RGBA4: - return 4; - case GL_RGBA8_OES: - case GL_BGRA8_EXT: - return 8; - case GL_RGB5_A1: - return 1; - case GL_RGB8_OES: - case GL_RGB565: - case GL_RGB32F_EXT: - case GL_RGB16F_EXT: - return 0; - default: - return 0; - } -} - -unsigned int GetRedSize(GLenum colorFormat) -{ - switch (colorFormat) - { - case GL_RGBA16F_EXT: - case GL_RGB16F_EXT: - return 16; - case GL_RGBA32F_EXT: - case GL_RGB32F_EXT: - return 32; - case GL_RGBA4: - return 4; - case GL_RGBA8_OES: - case GL_BGRA8_EXT: - case GL_RGB8_OES: - return 8; - case GL_RGB5_A1: - case GL_RGB565: - return 5; - default: - return 0; - } -} - -unsigned int GetGreenSize(GLenum colorFormat) -{ - switch (colorFormat) - { - case GL_RGBA16F_EXT: - case GL_RGB16F_EXT: - return 16; - case GL_RGBA32F_EXT: - case GL_RGB32F_EXT: - return 32; - case GL_RGBA4: - return 4; - case GL_RGBA8_OES: - case GL_BGRA8_EXT: - case GL_RGB8_OES: - return 8; - case GL_RGB5_A1: - return 5; - case GL_RGB565: - return 6; - default: - return 0; - } -} - -unsigned int GetBlueSize(GLenum colorFormat) -{ - switch (colorFormat) - { - case GL_RGBA16F_EXT: - case GL_RGB16F_EXT: - return 16; - case GL_RGBA32F_EXT: - case GL_RGB32F_EXT: - return 32; - case GL_RGBA4: - return 4; - case GL_RGBA8_OES: - case GL_BGRA8_EXT: - case GL_RGB8_OES: - return 8; - case GL_RGB5_A1: - case GL_RGB565: - return 5; - default: - return 0; - } -} - -unsigned int GetDepthSize(GLenum depthFormat) -{ - switch (depthFormat) - { - case GL_DEPTH_COMPONENT16: return 16; - case GL_DEPTH_COMPONENT32_OES: return 32; - case GL_DEPTH24_STENCIL8_OES: return 24; - default: return 0; - } -} - -unsigned int GetStencilSize(GLenum stencilFormat) -{ - switch (stencilFormat) - { - case GL_DEPTH24_STENCIL8_OES: return 8; - default: return 0; - } -} - -bool IsTriangleMode(GLenum drawMode) -{ - switch (drawMode) - { - case GL_TRIANGLES: - case GL_TRIANGLE_FAN: - case GL_TRIANGLE_STRIP: - return true; - case GL_POINTS: - case GL_LINES: - case GL_LINE_LOOP: - case GL_LINE_STRIP: - return false; - default: UNREACHABLE(); - } - - return false; -} - -} - -std::string getTempPath() -{ -#if !defined(ANGLE_OS_WINRT) - char path[MAX_PATH]; - DWORD pathLen = GetTempPathA(sizeof(path) / sizeof(path[0]), path); - if (pathLen == 0) - { - UNREACHABLE(); - return std::string(); - } - - UINT unique = GetTempFileNameA(path, "sh", 0, path); - if (unique == 0) - { - UNREACHABLE(); - return std::string(); - } -#else - static std::string path; - - while (path.empty()) { - ComPtr factory; - Wrappers::HStringReference classId(RuntimeClass_Windows_Storage_ApplicationData); - HRESULT result = RoGetActivationFactory(classId.Get(), IID_PPV_ARGS(&factory)); - if (FAILED(result)) - break; - - ComPtr applicationData; - result = factory->get_Current(&applicationData); - if (FAILED(result)) - break; - - ComPtr storageFolder; - result = applicationData->get_LocalFolder(&storageFolder); - if (FAILED(result)) - break; - - ComPtr localFolder; - result = storageFolder.As(&localFolder); - if (FAILED(result)) - break; - - HSTRING localFolderPath; - result = localFolder->get_Path(&localFolderPath); - if (FAILED(result)) - break; - - std::wstring_convert< std::codecvt_utf8 > converter; - path = converter.to_bytes(WindowsGetStringRawBuffer(localFolderPath, NULL)); - if (path.empty()) - { - UNREACHABLE(); - break; - } - } -#endif - - return path; -} - -void writeFile(const char* path, const void* content, size_t size) -{ - FILE* file = fopen(path, "w"); - if (!file) - { - UNREACHABLE(); - return; - } - - fwrite(content, sizeof(char), size, file); - fclose(file); -} diff --git a/src/3rdparty/angle/src/libGLESv2/utilities.h b/src/3rdparty/angle/src/libGLESv2/utilities.h deleted file mode 100644 index ed663ebca2..0000000000 --- a/src/3rdparty/angle/src/libGLESv2/utilities.h +++ /dev/null @@ -1,67 +0,0 @@ -// -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// - -// utilities.h: Conversion functions and other utility routines. - -#ifndef LIBGLESV2_UTILITIES_H -#define LIBGLESV2_UTILITIES_H - -#define GL_APICALL -#include -#include - -#include - -namespace gl -{ - -struct Color; - -int UniformComponentCount(GLenum type); -GLenum UniformComponentType(GLenum type); -size_t UniformInternalSize(GLenum type); -size_t UniformExternalSize(GLenum type); -int VariableRowCount(GLenum type); -int VariableColumnCount(GLenum type); - -int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize); - -void MakeValidSize(bool isImage, bool isCompressed, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset); -int ComputePixelSize(GLint internalformat); -GLsizei ComputePitch(GLsizei width, GLint internalformat, GLint alignment); -GLsizei ComputeCompressedPitch(GLsizei width, GLenum format); -GLsizei ComputeCompressedSize(GLsizei width, GLsizei height, GLenum format); -GLsizei ComputeTypeSize(GLenum type); -bool IsCompressed(GLenum format); -bool IsDepthTexture(GLenum format); -bool IsStencilTexture(GLenum format); -bool IsCubemapTextureTarget(GLenum target); -bool IsInternalTextureTarget(GLenum target); -GLint ConvertSizedInternalFormat(GLenum format, GLenum type); -GLenum ExtractFormat(GLenum internalformat); -GLenum ExtractType(GLenum internalformat); - -bool IsColorRenderable(GLenum internalformat); -bool IsDepthRenderable(GLenum internalformat); -bool IsStencilRenderable(GLenum internalformat); - -bool IsFloat32Format(GLint internalformat); -bool IsFloat16Format(GLint internalformat); - -GLuint GetAlphaSize(GLenum colorFormat); -GLuint GetRedSize(GLenum colorFormat); -GLuint GetGreenSize(GLenum colorFormat); -GLuint GetBlueSize(GLenum colorFormat); -GLuint GetDepthSize(GLenum depthFormat); -GLuint GetStencilSize(GLenum stencilFormat); -bool IsTriangleMode(GLenum drawMode); - -} - -std::string getTempPath(); -void writeFile(const char* path, const void* data, size_t size); - -#endif // LIBGLESV2_UTILITIES_H diff --git a/src/3rdparty/angle/src/libGLESv2/validationES.cpp b/src/3rdparty/angle/src/libGLESv2/validationES.cpp new file mode 100644 index 0000000000..309c4daedb --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/validationES.cpp @@ -0,0 +1,1583 @@ +#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 +// found in the LICENSE file. +// + +// validationES.h: Validation functions for generic OpenGL ES entry point parameters + +#include "libGLESv2/validationES.h" +#include "libGLESv2/validationES2.h" +#include "libGLESv2/validationES3.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/Texture.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" +#include "libGLESv2/formatutils.h" +#include "libGLESv2/main.h" +#include "libGLESv2/Query.h" +#include "libGLESv2/ProgramBinary.h" +#include "libGLESv2/TransformFeedback.h" +#include "libGLESv2/VertexArray.h" + +#include "common/mathutil.h" +#include "common/utilities.h" + +namespace gl +{ + +bool ValidCap(const Context *context, GLenum cap) +{ + switch (cap) + { + case GL_CULL_FACE: + case GL_POLYGON_OFFSET_FILL: + case GL_SAMPLE_ALPHA_TO_COVERAGE: + case GL_SAMPLE_COVERAGE: + case GL_SCISSOR_TEST: + case GL_STENCIL_TEST: + case GL_DEPTH_TEST: + case GL_BLEND: + case GL_DITHER: + return true; + case GL_PRIMITIVE_RESTART_FIXED_INDEX: + case GL_RASTERIZER_DISCARD: + return (context->getClientVersion() >= 3); + default: + return false; + } +} + +bool ValidTextureTarget(const Context *context, GLenum target) +{ + switch (target) + { + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP: + return true; + + case GL_TEXTURE_3D: + case GL_TEXTURE_2D_ARRAY: + return (context->getClientVersion() >= 3); + + default: + return false; + } +} + +// This function differs from ValidTextureTarget in that the target must be +// usable as the destination of a 2D operation-- so a cube face is valid, but +// GL_TEXTURE_CUBE_MAP is not. +// Note: duplicate of IsInternalTextureTarget +bool ValidTexture2DDestinationTarget(const Context *context, GLenum target) +{ + switch (target) + { + case GL_TEXTURE_2D: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + return true; + case GL_TEXTURE_2D_ARRAY: + case GL_TEXTURE_3D: + return (context->getClientVersion() >= 3); + default: + return false; + } +} + +bool ValidFramebufferTarget(GLenum target) +{ + META_ASSERT(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER); + + switch (target) + { + case GL_FRAMEBUFFER: return true; + case GL_READ_FRAMEBUFFER: return true; + case GL_DRAW_FRAMEBUFFER: return true; + default: return false; + } +} + +bool ValidBufferTarget(const Context *context, GLenum target) +{ + switch (target) + { + case GL_ARRAY_BUFFER: + case GL_ELEMENT_ARRAY_BUFFER: + return true; + + case GL_PIXEL_PACK_BUFFER: + case GL_PIXEL_UNPACK_BUFFER: + return context->getExtensions().pixelBufferObject; + + case GL_COPY_READ_BUFFER: + case GL_COPY_WRITE_BUFFER: + case GL_TRANSFORM_FEEDBACK_BUFFER: + case GL_UNIFORM_BUFFER: + return (context->getClientVersion() >= 3); + + default: + return false; + } +} + +bool ValidBufferParameter(const Context *context, GLenum pname) +{ + switch (pname) + { + case GL_BUFFER_USAGE: + case GL_BUFFER_SIZE: + return true; + + // GL_BUFFER_MAP_POINTER is a special case, and may only be + // queried with GetBufferPointerv + case GL_BUFFER_ACCESS_FLAGS: + case GL_BUFFER_MAPPED: + case GL_BUFFER_MAP_OFFSET: + case GL_BUFFER_MAP_LENGTH: + return (context->getClientVersion() >= 3); + + default: + return false; + } +} + +bool ValidMipLevel(const Context *context, GLenum target, GLint level) +{ + size_t maxDimension = 0; + switch (target) + { + case GL_TEXTURE_2D: maxDimension = context->getCaps().max2DTextureSize; break; + case GL_TEXTURE_CUBE_MAP: + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: maxDimension = context->getCaps().maxCubeMapTextureSize; break; + case GL_TEXTURE_3D: maxDimension = context->getCaps().max3DTextureSize; break; + case GL_TEXTURE_2D_ARRAY: maxDimension = context->getCaps().max2DTextureSize; break; + default: UNREACHABLE(); + } + + return level <= gl::log2(maxDimension); +} + +bool ValidImageSize(const gl::Context *context, GLenum target, GLint level, + GLsizei width, GLsizei height, GLsizei depth) +{ + if (level < 0 || width < 0 || height < 0 || depth < 0) + { + return false; + } + + if (!context->getExtensions().textureNPOT && + (level != 0 && (!gl::isPow2(width) || !gl::isPow2(height) || !gl::isPow2(depth)))) + { + return false; + } + + if (!ValidMipLevel(context, target, level)) + { + return false; + } + + return true; +} + +bool ValidCompressedImageSize(const gl::Context *context, GLenum internalFormat, GLsizei width, GLsizei height) +{ + if (!IsFormatCompressed(internalFormat)) + { + 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)) + { + return false; + } + + return true; +} + +bool ValidQueryType(const Context *context, GLenum queryType) +{ + META_ASSERT(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT); + META_ASSERT(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT); + + switch (queryType) + { + case GL_ANY_SAMPLES_PASSED: + case GL_ANY_SAMPLES_PASSED_CONSERVATIVE: + return true; + case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN: + return (context->getClientVersion() >= 3); + default: + return false; + } +} + +bool ValidProgram(const Context *context, GLuint id) +{ + // ES3 spec (section 2.11.1) -- "Commands that accept shader or program object names will generate the + // error INVALID_VALUE if the provided name is not the name of either a shader or program object and + // INVALID_OPERATION if the provided name identifies an object that is not the expected type." + + if (context->getProgram(id) != NULL) + { + return true; + } + else if (context->getShader(id) != NULL) + { + // ID is the wrong type + return gl::error(GL_INVALID_OPERATION, false); + } + else + { + // No shader/program object has this ID + return gl::error(GL_INVALID_VALUE, false); + } +} + +bool ValidateAttachmentTarget(const gl::Context *context, GLenum attachment) +{ + if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT) + { + const unsigned int colorAttachment = (attachment - GL_COLOR_ATTACHMENT0_EXT); + + if (colorAttachment >= context->getCaps().maxColorAttachments) + { + return gl::error(GL_INVALID_VALUE, false); + } + } + else + { + switch (attachment) + { + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + break; + + case GL_DEPTH_STENCIL_ATTACHMENT: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + + default: + return gl::error(GL_INVALID_ENUM, false); + } + } + + return true; +} + +bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, GLsizei height, + bool angleExtension) +{ + switch (target) + { + case GL_RENDERBUFFER: + break; + default: + return gl::error(GL_INVALID_ENUM, false); + } + + if (width < 0 || height < 0 || samples < 0) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (!gl::IsValidInternalFormat(internalformat, context->getExtensions(), context->getClientVersion())) + { + return gl::error(GL_INVALID_ENUM, 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)) + { + 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); + } + + const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat); + if (!formatCaps.renderable) + { + return gl::error(GL_INVALID_ENUM, false); + } + + if (static_cast(std::max(width, height)) > context->getCaps().maxRenderbufferSize) + { + return gl::error(GL_INVALID_VALUE, false); + } + + // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal + // to MAX_SAMPLES_ANGLE (Context::getMaxSupportedSamples) while the ES3.0 spec (section 4.4.2) + // states that samples must be less than or equal to the maximum samples for the specified + // internal format. + if (angleExtension) + { + if (samples > context->getMaxSupportedSamples()) + { + return gl::error(GL_INVALID_VALUE, false); + } + } + else + { + if (samples > context->getMaxSupportedFormatSamples(internalformat)) + { + return gl::error(GL_INVALID_VALUE, false); + } + } + + GLuint handle = context->getState().getRenderbufferId(); + if (handle == 0) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + return true; +} + +bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment, + GLenum renderbuffertarget, GLuint renderbuffer) +{ + if (!ValidFramebufferTarget(target)) + { + return gl::error(GL_INVALID_ENUM, false); + } + + gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); + + if (!framebuffer || (framebufferHandle == 0 && renderbuffer != 0)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (!ValidateAttachmentTarget(context, attachment)) + { + return false; + } + + // [OpenGL ES 2.0.25] Section 4.4.3 page 112 + // [OpenGL ES 3.0.2] Section 4.4.2 page 201 + // 'renderbuffer' must be either zero or the name of an existing renderbuffer object of + // type 'renderbuffertarget', otherwise an INVALID_OPERATION error is generated. + if (renderbuffer != 0) + { + if (!context->getRenderbuffer(renderbuffer)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + + return true; +} + +static bool IsPartialBlit(gl::Context *context, gl::FramebufferAttachment *readBuffer, gl::FramebufferAttachment *writeBuffer, + GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1) +{ + if (srcX0 != 0 || srcY0 != 0 || dstX0 != 0 || dstY0 != 0 || + dstX1 != writeBuffer->getWidth() || dstY1 != writeBuffer->getHeight() || + srcX1 != readBuffer->getWidth() || srcY1 != readBuffer->getHeight()) + { + return true; + } + else if (context->getState().isScissorTestEnabled()) + { + const Rectangle &scissor = context->getState().getScissor(); + + return scissor.x > 0 || scissor.y > 0 || + scissor.width < writeBuffer->getWidth() || + scissor.height < writeBuffer->getHeight(); + } + else + { + return false; + } +} + +bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, + GLenum filter, bool fromAngleExtension) +{ + switch (filter) + { + case GL_NEAREST: + break; + case GL_LINEAR: + if (fromAngleExtension) + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + default: + return gl::error(GL_INVALID_ENUM, false); + } + + if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (mask == 0) + { + // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no + // buffers are copied. + return false; + } + + if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)) + { + ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation."); + return gl::error(GL_INVALID_OPERATION, 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); + } + + if (context->getState().getReadFramebuffer()->id() == context->getState().getDrawFramebuffer()->id()) + { + if (fromAngleExtension) + { + ERR("Blits with the same source and destination framebuffer are not supported by this " + "implementation."); + } + return gl::error(GL_INVALID_OPERATION, false); + } + + gl::Framebuffer *readFramebuffer = context->getState().getReadFramebuffer(); + gl::Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer(); + if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE || + !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) + { + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + } + + if (drawFramebuffer->getSamples() != 0) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1; + + if (mask & GL_COLOR_BUFFER_BIT) + { + gl::FramebufferAttachment *readColorBuffer = readFramebuffer->getReadColorbuffer(); + gl::FramebufferAttachment *drawColorBuffer = drawFramebuffer->getFirstColorbuffer(); + + if (readColorBuffer && drawColorBuffer) + { + GLenum readInternalFormat = readColorBuffer->getActualFormat(); + GLenum readComponentType = gl::GetComponentType(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); + + // 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)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (readComponentType == GL_UNSIGNED_INT && drawComponentType != GL_UNSIGNED_INT) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (readComponentType == GL_INT && drawComponentType != GL_INT) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawInternalFormat || !sameBounds)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + } + + if ((readComponentType == GL_INT || readComponentType == GL_UNSIGNED_INT) && filter == GL_LINEAR) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (fromAngleExtension) + { + const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType(); + if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) + { + if (drawFramebuffer->isEnabledColorAttachment(colorAttachment)) + { + FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(colorAttachment); + ASSERT(attachment); + + if (attachment->type() != GL_TEXTURE_2D && attachment->type() != GL_RENDERBUFFER) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (attachment->getActualFormat() != readColorBuffer->getActualFormat()) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + } + if (readFramebuffer->getSamples() != 0 && IsPartialBlit(context, readColorBuffer, drawColorBuffer, + srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + } + } + + if (mask & GL_DEPTH_BUFFER_BIT) + { + gl::FramebufferAttachment *readDepthBuffer = readFramebuffer->getDepthbuffer(); + gl::FramebufferAttachment *drawDepthBuffer = drawFramebuffer->getDepthbuffer(); + + if (readDepthBuffer && drawDepthBuffer) + { + if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat()) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (readDepthBuffer->getSamples() > 0 && !sameBounds) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (fromAngleExtension) + { + if (IsPartialBlit(context, readDepthBuffer, drawDepthBuffer, + srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) + { + ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); + return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted + } + + if (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + } + } + + if (mask & GL_STENCIL_BUFFER_BIT) + { + gl::FramebufferAttachment *readStencilBuffer = readFramebuffer->getStencilbuffer(); + gl::FramebufferAttachment *drawStencilBuffer = drawFramebuffer->getStencilbuffer(); + + if (readStencilBuffer && drawStencilBuffer) + { + if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat()) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (readStencilBuffer->getSamples() > 0 && !sameBounds) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (fromAngleExtension) + { + if (IsPartialBlit(context, readStencilBuffer, drawStencilBuffer, + srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1)) + { + ERR("Only whole-buffer depth and stencil blits are supported by this implementation."); + return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted + } + + if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + } + } + + return true; +} + +bool ValidateGetVertexAttribParameters(GLenum pname, int clientVersion) +{ + switch (pname) + { + case GL_VERTEX_ATTRIB_ARRAY_ENABLED: + case GL_VERTEX_ATTRIB_ARRAY_SIZE: + case GL_VERTEX_ATTRIB_ARRAY_STRIDE: + case GL_VERTEX_ATTRIB_ARRAY_TYPE: + case GL_VERTEX_ATTRIB_ARRAY_NORMALIZED: + case GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: + case GL_CURRENT_VERTEX_ATTRIB: + return true; + + case GL_VERTEX_ATTRIB_ARRAY_DIVISOR: + // Don't verify ES3 context because GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE uses + // the same constant. + META_ASSERT(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE); + return true; + + case GL_VERTEX_ATTRIB_ARRAY_INTEGER: + return ((clientVersion >= 3) ? true : gl::error(GL_INVALID_ENUM, false)); + + default: + return gl::error(GL_INVALID_ENUM, false); + } +} + +bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param) +{ + switch (pname) + { + case GL_TEXTURE_WRAP_R: + case GL_TEXTURE_SWIZZLE_R: + case GL_TEXTURE_SWIZZLE_G: + case GL_TEXTURE_SWIZZLE_B: + case GL_TEXTURE_SWIZZLE_A: + case GL_TEXTURE_BASE_LEVEL: + case GL_TEXTURE_MAX_LEVEL: + case GL_TEXTURE_COMPARE_MODE: + case GL_TEXTURE_COMPARE_FUNC: + case GL_TEXTURE_MIN_LOD: + case GL_TEXTURE_MAX_LOD: + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + + default: break; + } + + switch (pname) + { + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + case GL_TEXTURE_WRAP_R: + switch (param) + { + case GL_REPEAT: + case GL_CLAMP_TO_EDGE: + case GL_MIRRORED_REPEAT: + return true; + default: + return gl::error(GL_INVALID_ENUM, false); + } + + case GL_TEXTURE_MIN_FILTER: + switch (param) + { + case GL_NEAREST: + case GL_LINEAR: + case GL_NEAREST_MIPMAP_NEAREST: + case GL_LINEAR_MIPMAP_NEAREST: + case GL_NEAREST_MIPMAP_LINEAR: + case GL_LINEAR_MIPMAP_LINEAR: + return true; + default: + return gl::error(GL_INVALID_ENUM, false); + } + break; + + case GL_TEXTURE_MAG_FILTER: + switch (param) + { + case GL_NEAREST: + case GL_LINEAR: + return true; + default: + return gl::error(GL_INVALID_ENUM, false); + } + break; + + case GL_TEXTURE_USAGE_ANGLE: + switch (param) + { + case GL_NONE: + case GL_FRAMEBUFFER_ATTACHMENT_ANGLE: + return true; + default: + return gl::error(GL_INVALID_ENUM, false); + } + break; + + case GL_TEXTURE_MAX_ANISOTROPY_EXT: + if (!context->getExtensions().textureFilterAnisotropic) + { + return gl::error(GL_INVALID_ENUM, false); + } + + // we assume the parameter passed to this validation method is truncated, not rounded + if (param < 1) + { + return gl::error(GL_INVALID_VALUE, false); + } + return true; + + case GL_TEXTURE_MIN_LOD: + case GL_TEXTURE_MAX_LOD: + // any value is permissible + return true; + + case GL_TEXTURE_COMPARE_MODE: + // Acceptable mode parameters from GLES 3.0.2 spec, table 3.17 + switch (param) + { + case GL_NONE: + case GL_COMPARE_REF_TO_TEXTURE: + return true; + default: + return gl::error(GL_INVALID_ENUM, false); + } + break; + + case GL_TEXTURE_COMPARE_FUNC: + // Acceptable function parameters from GLES 3.0.2 spec, table 3.17 + switch (param) + { + case GL_LEQUAL: + case GL_GEQUAL: + case GL_LESS: + case GL_GREATER: + case GL_EQUAL: + case GL_NOTEQUAL: + case GL_ALWAYS: + case GL_NEVER: + return true; + default: + return gl::error(GL_INVALID_ENUM, false); + } + break; + + case GL_TEXTURE_SWIZZLE_R: + case GL_TEXTURE_SWIZZLE_G: + case GL_TEXTURE_SWIZZLE_B: + case GL_TEXTURE_SWIZZLE_A: + switch (param) + { + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_ZERO: + case GL_ONE: + return true; + default: + return gl::error(GL_INVALID_ENUM, false); + } + break; + + case GL_TEXTURE_BASE_LEVEL: + case GL_TEXTURE_MAX_LEVEL: + if (param < 0) + { + return gl::error(GL_INVALID_VALUE, false); + } + return true; + + default: + return gl::error(GL_INVALID_ENUM, false); + } +} + +bool ValidateSamplerObjectParameter(GLenum pname) +{ + switch (pname) + { + case GL_TEXTURE_MIN_FILTER: + case GL_TEXTURE_MAG_FILTER: + case GL_TEXTURE_WRAP_S: + case GL_TEXTURE_WRAP_T: + case GL_TEXTURE_WRAP_R: + case GL_TEXTURE_MIN_LOD: + case GL_TEXTURE_MAX_LOD: + case GL_TEXTURE_COMPARE_MODE: + case GL_TEXTURE_COMPARE_FUNC: + return true; + + default: + return gl::error(GL_INVALID_ENUM, false); + } +} + +bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels) +{ + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + ASSERT(framebuffer); + + if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) + { + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + } + + if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (!framebuffer->getReadColorbuffer()) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + GLenum currentInternalFormat, currentFormat, currentType; + GLuint clientVersion = context->getClientVersion(); + + context->getCurrentReadFormatType(¤tInternalFormat, ¤tFormat, ¤tType); + + bool validReadFormat = (clientVersion < 3) ? ValidES2ReadFormatType(context, format, type) : + ValidES3ReadFormatType(context, currentInternalFormat, format, type); + + if (!(currentFormat == format && currentType == type) && !validReadFormat) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + GLenum sizedInternalFormat = IsSizedInternalFormat(format) ? format + : GetSizedInternalFormat(format, type); + + GLsizei outputPitch = GetRowPitch(sizedInternalFormat, 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); + } + } + + return true; +} + +bool ValidateBeginQuery(gl::Context *context, GLenum target, GLuint id) +{ + if (!ValidQueryType(context, target)) + { + return gl::error(GL_INVALID_ENUM, false); + } + + if (id == 0) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an + // of zero, if the active query object name for is non-zero (for the + // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if + // the active query for either target is non-zero), if is the name of an + // existing query object whose type does not match , or if is the + // active query object name for any query type, the error INVALID_OPERATION is + // generated. + + // Ensure no other queries are active + // NOTE: If other queries than occlusion are supported, we will need to check + // separately that: + // a) The query ID passed is not the current active query for any target/type + // b) There are no active queries for the requested target (and in the case + // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, + // no query may be active for either if glBeginQuery targets either. + if (context->getState().isQueryActive()) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + Query *queryObject = context->getQuery(id, true, target); + + // check that name was obtained with glGenQueries + if (!queryObject) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + // check for type mismatch + if (queryObject->getType() != target) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + return true; +} + +bool ValidateEndQuery(gl::Context *context, GLenum target) +{ + if (!ValidQueryType(context, target)) + { + return gl::error(GL_INVALID_ENUM, 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); + } + + return true; +} + +static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniformType, + GLint location, GLsizei count, LinkedUniform **uniformOut) +{ + if (count < 0) + { + return gl::error(GL_INVALID_VALUE, false); + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + if (!programBinary) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (location == -1) + { + // Silently ignore the uniform command + return false; + } + + if (!programBinary->isValidUniformLocation(location)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + LinkedUniform *uniform = programBinary->getUniformByLocation(location); + + // attempting to write an array to a non-array uniform is an INVALID_OPERATION + if (uniform->elementCount() == 1 && count > 1) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + *uniformOut = uniform; + return true; +} + +bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count) +{ + // Check for ES3 uniform entry points + if (VariableComponentType(uniformType) == GL_UNSIGNED_INT && context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + LinkedUniform *uniform = NULL; + if (!ValidateUniformCommonBase(context, uniformType, location, count, &uniform)) + { + return false; + } + + GLenum targetBoolType = VariableBoolVectorType(uniformType); + bool samplerUniformCheck = (IsSampler(uniform->type) && uniformType == GL_INT); + if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + return true; +} + +bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count, + GLboolean transpose) +{ + // Check for ES3 uniform entry points + int rows = VariableRowCount(matrixType); + int cols = VariableColumnCount(matrixType); + if (rows != cols && context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (transpose != GL_FALSE && context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_VALUE, false); + } + + LinkedUniform *uniform = NULL; + if (!ValidateUniformCommonBase(context, matrixType, location, count, &uniform)) + { + return false; + } + + if (uniform->type != matrixType) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + return true; +} + +bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams) +{ + if (!context->getQueryParameterInfo(pname, nativeType, numParams)) + { + return gl::error(GL_INVALID_ENUM, false); + } + + if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15) + { + unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0); + + if (colorAttachment >= context->getCaps().maxDrawBuffers) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + + switch (pname) + { + case GL_TEXTURE_BINDING_2D: + case GL_TEXTURE_BINDING_CUBE_MAP: + case GL_TEXTURE_BINDING_3D: + case GL_TEXTURE_BINDING_2D_ARRAY: + if (context->getState().getActiveSampler() >= context->getMaximumCombinedTextureImageUnits()) + { + return gl::error(GL_INVALID_OPERATION, false); + } + break; + + case GL_IMPLEMENTATION_COLOR_READ_TYPE: + case GL_IMPLEMENTATION_COLOR_READ_FORMAT: + { + Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + ASSERT(framebuffer); + if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); + if (!attachment) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + break; + + default: + break; + } + + // pname is valid, but there are no parameters to return + if (numParams == 0) + { + return false; + } + + return true; +} + +bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, + GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, + GLint border, GLenum *textureFormatOut) +{ + + if (!ValidTexture2DDestinationTarget(context, target)) + { + return gl::error(GL_INVALID_ENUM, false); + } + + if (level < 0 || xoffset < 0 || yoffset < 0 || zoffset < 0 || width < 0 || height < 0) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (std::numeric_limits::max() - xoffset < width || std::numeric_limits::max() - yoffset < height) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (border != 0) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (!ValidMipLevel(context, target, level)) + { + return gl::error(GL_INVALID_VALUE, false); + } + + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) + { + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + } + + if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0) + { + return gl::error(GL_INVALID_OPERATION, 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; + GLuint maxDimension = 0; + + switch (target) + { + case GL_TEXTURE_2D: + { + gl::Texture2D *texture2d = context->getTexture2D(); + if (texture2d) + { + textureInternalFormat = texture2d->getInternalFormat(level); + textureCompressed = texture2d->isCompressed(level); + textureIsDepth = texture2d->isDepth(level); + textureLevelWidth = texture2d->getWidth(level); + textureLevelHeight = texture2d->getHeight(level); + textureLevelDepth = 1; + texture = texture2d; + maxDimension = caps.max2DTextureSize; + } + } + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + { + gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); + if (textureCube) + { + textureInternalFormat = textureCube->getInternalFormat(target, level); + textureCompressed = textureCube->isCompressed(target, level); + textureIsDepth = false; + textureLevelWidth = textureCube->getWidth(target, level); + textureLevelHeight = textureCube->getHeight(target, level); + textureLevelDepth = 1; + texture = textureCube; + maxDimension = caps.maxCubeMapTextureSize; + } + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + gl::Texture2DArray *texture2dArray = context->getTexture2DArray(); + if (texture2dArray) + { + textureInternalFormat = texture2dArray->getInternalFormat(level); + textureCompressed = texture2dArray->isCompressed(level); + textureIsDepth = texture2dArray->isDepth(level); + textureLevelWidth = texture2dArray->getWidth(level); + textureLevelHeight = texture2dArray->getHeight(level); + textureLevelDepth = texture2dArray->getLayers(level); + texture = texture2dArray; + maxDimension = caps.max2DTextureSize; + } + } + break; + + case GL_TEXTURE_3D: + { + gl::Texture3D *texture3d = context->getTexture3D(); + if (texture3d) + { + textureInternalFormat = texture3d->getInternalFormat(level); + textureCompressed = texture3d->isCompressed(level); + textureIsDepth = texture3d->isDepth(level); + textureLevelWidth = texture3d->getWidth(level); + textureLevelHeight = texture3d->getHeight(level); + textureLevelDepth = texture3d->getDepth(level); + texture = texture3d; + maxDimension = caps.max3DTextureSize; + } + } + break; + + default: + return gl::error(GL_INVALID_ENUM, false); + } + + if (!texture) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (texture->isImmutable() && !isSubImage) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (textureIsDepth) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (textureCompressed) + { + GLint blockWidth = GetCompressedBlockWidth(textureInternalFormat); + GLint blockHeight = GetCompressedBlockHeight(textureInternalFormat); + + if (((width % blockWidth) != 0 && width != textureLevelWidth) || + ((height % blockHeight) != 0 && height != textureLevelHeight)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + + if (isSubImage) + { + if (xoffset + width > textureLevelWidth || + yoffset + height > textureLevelHeight || + zoffset >= textureLevelDepth) + { + return gl::error(GL_INVALID_VALUE, false); + } + } + else + { + if (IsCubemapTextureTarget(target) && width != height) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (!IsValidInternalFormat(internalformat, context->getExtensions(), context->getClientVersion())) + { + return gl::error(GL_INVALID_ENUM, false); + } + + int maxLevelDimension = (maxDimension >> level); + if (static_cast(width) > maxLevelDimension || static_cast(height) > maxLevelDimension) + { + return gl::error(GL_INVALID_VALUE, false); + } + } + + *textureFormatOut = textureInternalFormat; + return true; +} + +static bool ValidateDrawBase(const gl::Context *context, GLenum mode, GLsizei count) +{ + switch (mode) + { + case GL_POINTS: + case GL_LINES: + case GL_LINE_LOOP: + case GL_LINE_STRIP: + case GL_TRIANGLES: + case GL_TRIANGLE_STRIP: + case GL_TRIANGLE_FAN: + break; + default: + return gl::error(GL_INVALID_ENUM, false); + } + + if (count < 0) + { + return gl::error(GL_INVALID_VALUE, false); + } + + // Check for mapped buffers + if (context->hasMappedBuffer(GL_ARRAY_BUFFER)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + const gl::DepthStencilState &depthStencilState = context->getState().getDepthStencilState(); + if (depthStencilState.stencilWritemask != depthStencilState.stencilBackWritemask || + context->getState().getStencilRef() != context->getState().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); + } + + const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer(); + if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE) + { + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + } + + if (context->getState().getCurrentProgramId() == 0) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary(); + if (!programBinary->validateSamplers(NULL)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + // No-op if zero count + return (count > 0); +} + +bool ValidateDrawArrays(const gl::Context *context, GLenum mode, GLint first, GLsizei count) +{ + if (first < 0) + { + return gl::error(GL_INVALID_VALUE, false); + } + + gl::TransformFeedback *curTransformFeedback = context->getState().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); + } + + if (!ValidateDrawBase(context, mode, count)) + { + return false; + } + + return true; +} + +bool ValidateDrawArraysInstanced(const gl::Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount) +{ + if (primcount < 0) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (!ValidateDrawArrays(context, mode, first, count)) + { + return false; + } + + // No-op if zero primitive count + return (primcount > 0); +} + +bool ValidateDrawElements(const gl::Context *context, GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) +{ + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT: + break; + case GL_UNSIGNED_INT: + if (!context->getExtensions().elementIndexUint) + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + default: + return gl::error(GL_INVALID_ENUM, false); + } + + gl::TransformFeedback *curTransformFeedback = context->getState().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); + } + + // Check for mapped buffers + if (context->hasMappedBuffer(GL_ELEMENT_ARRAY_BUFFER)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + gl::VertexArray *vao = context->getState().getVertexArray(); + if (!indices && !vao->getElementArrayBuffer()) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (!ValidateDrawBase(context, mode, count)) + { + return false; + } + + return true; +} + +bool ValidateDrawElementsInstanced(const gl::Context *context, GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices, GLsizei primcount) +{ + if (primcount < 0) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (!ValidateDrawElements(context, mode, count, type, indices)) + { + return false; + } + + // No-op zero primitive count + return (primcount > 0); +} + +bool ValidateFramebufferTextureBase(const gl::Context *context, GLenum target, GLenum attachment, + GLuint texture, GLint level) +{ + if (!ValidFramebufferTarget(target)) + { + return gl::error(GL_INVALID_ENUM, false); + } + + if (!ValidateAttachmentTarget(context, attachment)) + { + return false; + } + + if (texture != 0) + { + gl::Texture *tex = context->getTexture(texture); + + if (tex == NULL) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (level < 0) + { + return gl::error(GL_INVALID_VALUE, false); + } + } + + const gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target); + GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id(); + + if (framebufferHandle == 0 || !framebuffer) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + return true; +} + +bool ValidateFramebufferTexture2D(const gl::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); + } + + if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level)) + { + return false; + } + + if (texture != 0) + { + gl::Texture *tex = context->getTexture(texture); + ASSERT(tex); + + const gl::Caps &caps = context->getCaps(); + + switch (textarget) + { + case GL_TEXTURE_2D: + { + if (level > gl::log2(caps.max2DTextureSize)) + { + return gl::error(GL_INVALID_VALUE, false); + } + if (tex->getTarget() != GL_TEXTURE_2D) + { + return gl::error(GL_INVALID_OPERATION, false); + } + gl::Texture2D *tex2d = static_cast(tex); + if (tex2d->isCompressed(level)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + { + if (level > gl::log2(caps.maxCubeMapTextureSize)) + { + return gl::error(GL_INVALID_VALUE, false); + } + if (tex->getTarget() != GL_TEXTURE_CUBE_MAP) + { + return gl::error(GL_INVALID_OPERATION, false); + } + gl::TextureCubeMap *texcube = static_cast(tex); + if (texcube->isCompressed(textarget, level)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + break; + + default: + return gl::error(GL_INVALID_ENUM, false); + } + } + + return true; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/validationES.h b/src/3rdparty/angle/src/libGLESv2/validationES.h new file mode 100644 index 0000000000..849df36588 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/validationES.h @@ -0,0 +1,75 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// validationES.h: Validation functions for generic OpenGL ES entry point parameters + +#ifndef LIBGLESV2_VALIDATION_ES_H +#define LIBGLESV2_VALIDATION_ES_H + +namespace gl +{ + +class Context; + +bool ValidCap(const Context *context, GLenum cap); +bool ValidTextureTarget(const Context *context, GLenum target); +bool ValidTexture2DDestinationTarget(const Context *context, GLenum target); +bool ValidFramebufferTarget(GLenum target); +bool ValidBufferTarget(const Context *context, GLenum target); +bool ValidBufferParameter(const Context *context, GLenum pname); +bool ValidMipLevel(const Context *context, GLenum target, GLint level); +bool ValidImageSize(const 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 ValidateAttachmentTarget(const gl::Context *context, GLenum attachment); +bool ValidateRenderbufferStorageParameters(const gl::Context *context, GLenum target, GLsizei samples, + GLenum internalformat, GLsizei width, GLsizei height, + bool angleExtension); +bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment, + GLenum renderbuffertarget, GLuint renderbuffer); + +bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, + GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, + GLenum filter, bool fromAngleExtension); + +bool ValidateGetVertexAttribParameters(GLenum pname, int clientVersion); + +bool ValidateTexParamParameters(gl::Context *context, GLenum pname, GLint param); + +bool ValidateSamplerObjectParameter(GLenum pname); + +bool ValidateReadPixelsParameters(gl::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 ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, GLsizei count); +bool ValidateUniformMatrix(gl::Context *context, GLenum matrixType, GLint location, GLsizei count, + GLboolean transpose); + +bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams); + +bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, + GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, + GLint border, GLenum *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 ValidateFramebufferTextureBase(const gl::Context *context, GLenum target, GLenum attachment, + GLuint texture, GLint level); +bool ValidateFramebufferTexture2D(const gl::Context *context, GLenum target, GLenum attachment, + GLenum textarget, GLuint texture, GLint level); + +} + +#endif // LIBGLESV2_VALIDATION_ES_H diff --git a/src/3rdparty/angle/src/libGLESv2/validationES2.cpp b/src/3rdparty/angle/src/libGLESv2/validationES2.cpp new file mode 100644 index 0000000000..1a09400322 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/validationES2.cpp @@ -0,0 +1,892 @@ +#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 +// found in the LICENSE file. +// + +// validationES2.cpp: Validation functions for OpenGL ES 2.0 entry point parameters + +#include "libGLESv2/validationES2.h" +#include "libGLESv2/validationES.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/Texture.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/formatutils.h" +#include "libGLESv2/main.h" +#include "libGLESv2/FramebufferAttachment.h" + +#include "common/mathutil.h" +#include "common/utilities.h" + +namespace gl +{ + +static bool validateSubImageParams2D(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); + } + + if (compressed != texture->isCompressed(level)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (format != GL_NONE) + { + GLenum internalformat = gl::GetSizedInternalFormat(format, type); + if (internalformat != texture->getInternalFormat(level)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + + if (compressed) + { + if ((width % 4 != 0 && width != texture->getWidth(level)) || + (height % 4 != 0 && height != texture->getHeight(level))) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + + if (xoffset + width > texture->getWidth(level) || + yoffset + height > texture->getHeight(level)) + { + return gl::error(GL_INVALID_VALUE, false); + } + + return true; +} + +static bool validateSubImageParamsCube(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); + } + + if (compressed != texture->isCompressed(target, level)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (format != GL_NONE) + { + GLenum internalformat = gl::GetSizedInternalFormat(format, type); + if (internalformat != texture->getInternalFormat(target, level)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + + if (compressed) + { + if ((width % 4 != 0 && width != texture->getWidth(target, 0)) || + (height % 4 != 0 && height != texture->getHeight(target, 0))) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + + if (xoffset + width > texture->getWidth(target, level) || + yoffset + height > texture->getHeight(target, level)) + { + return gl::error(GL_INVALID_VALUE, false); + } + + return true; +} + +bool ValidateES2TexImageParameters(gl::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); + } + + if (!ValidImageSize(context, target, level, width, height, 1)) + { + return gl::error(GL_INVALID_VALUE, 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); + } + + if (!isSubImage && !isCompressed && internalformat != format) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + const gl::Caps &caps = context->getCaps(); + + gl::Texture *texture = NULL; + bool textureCompressed = false; + GLenum textureInternalFormat = GL_NONE; + GLint textureLevelWidth = 0; + GLint textureLevelHeight = 0; + switch (target) + { + case GL_TEXTURE_2D: + { + if (static_cast(width) > (caps.max2DTextureSize >> level) || + static_cast(height) > (caps.max2DTextureSize >> level)) + { + return gl::error(GL_INVALID_VALUE, false); + } + + gl::Texture2D *tex2d = context->getTexture2D(); + if (tex2d) + { + textureCompressed = tex2d->isCompressed(level); + textureInternalFormat = tex2d->getInternalFormat(level); + textureLevelWidth = tex2d->getWidth(level); + textureLevelHeight = tex2d->getHeight(level); + texture = tex2d; + } + + if (isSubImage && !validateSubImageParams2D(isCompressed, width, height, xoffset, yoffset, + level, format, type, tex2d)) + { + return false; + } + + texture = tex2d; + } + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + { + if (!isSubImage && width != height) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (static_cast(width) > (caps.maxCubeMapTextureSize >> level) || + static_cast(height) > (caps.maxCubeMapTextureSize >> level)) + { + return gl::error(GL_INVALID_VALUE, false); + } + + gl::TextureCubeMap *texCube = context->getTextureCubeMap(); + if (texCube) + { + textureCompressed = texCube->isCompressed(target, level); + textureInternalFormat = texCube->getInternalFormat(target, level); + textureLevelWidth = texCube->getWidth(target, level); + textureLevelHeight = texCube->getHeight(target, level); + texture = texCube; + } + + if (isSubImage && !validateSubImageParamsCube(isCompressed, width, height, xoffset, yoffset, + target, level, format, type, texCube)) + { + return false; + } + } + break; + + default: + return gl::error(GL_INVALID_ENUM, false); + } + + if (!texture) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (!isSubImage && texture->isImmutable()) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + // Verify zero border + if (border != 0) + { + return gl::error(GL_INVALID_VALUE, false); + } + + GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat; + if (isCompressed) + { + if (!ValidCompressedImageSize(context, actualInternalFormat, width, height)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + switch (actualInternalFormat) + { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + if (!context->getExtensions().textureCompressionDXT1) + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + if (!context->getExtensions().textureCompressionDXT1) + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + if (!context->getExtensions().textureCompressionDXT5) + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + default: + return gl::error(GL_INVALID_ENUM, false); + } + } + else + { + // validate by itself (used as secondary key below) + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT: + case GL_UNSIGNED_INT: + case GL_UNSIGNED_INT_24_8_OES: + case GL_HALF_FLOAT_OES: + case GL_FLOAT: + break; + default: + return gl::error(GL_INVALID_ENUM, false); + } + + // validate + combinations + // - invalid -> sets INVALID_ENUM + // - invalid + combination -> sets INVALID_OPERATION + switch (format) + { + case GL_ALPHA: + case GL_LUMINANCE: + case GL_LUMINANCE_ALPHA: + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_FLOAT: + case GL_HALF_FLOAT_OES: + break; + default: + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_RED: + case GL_RG: + if (!context->getExtensions().textureRG) + { + return gl::error(GL_INVALID_ENUM, false); + } + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_FLOAT: + case GL_HALF_FLOAT_OES: + break; + default: + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_RGB: + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_FLOAT: + case GL_HALF_FLOAT_OES: + break; + default: + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_RGBA: + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_4_4_4_4: + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_FLOAT: + case GL_HALF_FLOAT_OES: + break; + default: + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_BGRA_EXT: + switch (type) + { + case GL_UNSIGNED_BYTE: + break; + default: + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_SRGB_EXT: + case GL_SRGB_ALPHA_EXT: + if (!context->getExtensions().sRGB) + { + return gl::error(GL_INVALID_ENUM, false); + } + switch (type) + { + case GL_UNSIGNED_BYTE: + break; + default: + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: // error cases for compressed textures are handled below + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + break; + case GL_DEPTH_COMPONENT: + switch (type) + { + case GL_UNSIGNED_SHORT: + case GL_UNSIGNED_INT: + break; + default: + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_DEPTH_STENCIL_OES: + switch (type) + { + case GL_UNSIGNED_INT_24_8_OES: + break; + default: + return gl::error(GL_INVALID_OPERATION, false); + } + break; + default: + return gl::error(GL_INVALID_ENUM, false); + } + + switch (format) + { + 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); + } + else + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + if (context->getExtensions().textureCompressionDXT3) + { + return gl::error(GL_INVALID_OPERATION, false); + } + else + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + if (context->getExtensions().textureCompressionDXT5) + { + return gl::error(GL_INVALID_OPERATION, false); + } + else + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + case GL_DEPTH_COMPONENT: + case GL_DEPTH_STENCIL_OES: + if (!context->getExtensions().depthTextures) + { + return gl::error(GL_INVALID_VALUE, false); + } + if (target != GL_TEXTURE_2D) + { + return gl::error(GL_INVALID_OPERATION, 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); + } + break; + default: + break; + } + + if (type == GL_FLOAT) + { + if (!context->getExtensions().textureFloat) + { + return gl::error(GL_INVALID_ENUM, false); + } + } + else if (type == GL_HALF_FLOAT_OES) + { + if (!context->getExtensions().textureHalfFloat) + { + return gl::error(GL_INVALID_ENUM, false); + } + } + } + + return true; +} + + + +bool ValidateES2CopyTexImageParameters(gl::Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage, + GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height, + GLint border) +{ + GLenum textureInternalFormat = GL_NONE; + + if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage, + xoffset, yoffset, 0, x, y, width, height, border, &textureInternalFormat)) + { + return false; + } + + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat(); + GLenum textureFormat = gl::GetFormat(textureInternalFormat); + + // [OpenGL ES 2.0.24] table 3.9 + if (isSubImage) + { + switch (textureFormat) + { + case GL_ALPHA: + if (colorbufferFormat != GL_ALPHA8_EXT && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES) + { + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_LUMINANCE: + if (colorbufferFormat != GL_R8_EXT && + colorbufferFormat != GL_RG8_EXT && + colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES) + { + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_RED_EXT: + if (colorbufferFormat != GL_R8_EXT && + colorbufferFormat != GL_RG8_EXT && + colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES) + { + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_RG_EXT: + if (colorbufferFormat != GL_RG8_EXT && + colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES) + { + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_RGB: + if (colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES) + { + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_LUMINANCE_ALPHA: + case GL_RGBA: + if (colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_RGBA8_OES) + { + return gl::error(GL_INVALID_OPERATION, 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); + case GL_DEPTH_COMPONENT: + case GL_DEPTH_STENCIL_OES: + return gl::error(GL_INVALID_OPERATION, false); + default: + return gl::error(GL_INVALID_OPERATION, false); + } + } + else + { + switch (internalformat) + { + case GL_ALPHA: + if (colorbufferFormat != GL_ALPHA8_EXT && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_RGBA8_OES) + { + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_LUMINANCE: + if (colorbufferFormat != GL_R8_EXT && + colorbufferFormat != GL_RG8_EXT && + colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_RGBA8_OES) + { + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_RED_EXT: + if (colorbufferFormat != GL_R8_EXT && + colorbufferFormat != GL_RG8_EXT && + colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_RGBA8_OES) + { + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_RG_EXT: + if (colorbufferFormat != GL_RG8_EXT && + colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_RGBA8_OES) + { + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_RGB: + if (colorbufferFormat != GL_RGB565 && + colorbufferFormat != GL_RGB8_OES && + colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_RGBA8_OES) + { + return gl::error(GL_INVALID_OPERATION, false); + } + break; + case GL_LUMINANCE_ALPHA: + case GL_RGBA: + if (colorbufferFormat != GL_RGBA4 && + colorbufferFormat != GL_RGB5_A1 && + colorbufferFormat != GL_BGRA8_EXT && + colorbufferFormat != GL_RGBA8_OES) + { + return gl::error(GL_INVALID_OPERATION, 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); + } + else + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + if (context->getExtensions().textureCompressionDXT3) + { + return gl::error(GL_INVALID_OPERATION, false); + } + else + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + if (context->getExtensions().textureCompressionDXT5) + { + return gl::error(GL_INVALID_OPERATION, false); + } + else + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + case GL_DEPTH_COMPONENT: + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT32_OES: + case GL_DEPTH_STENCIL_OES: + case GL_DEPTH24_STENCIL8_OES: + if (context->getExtensions().depthTextures) + { + return gl::error(GL_INVALID_OPERATION, false); + } + else + { + return gl::error(GL_INVALID_ENUM, false); + } + default: + return gl::error(GL_INVALID_ENUM, false); + } + } + + // If width or height is zero, it is a no-op. Return false without setting an error. + return (width > 0 && height > 0); +} + +bool ValidateES2TexStorageParameters(gl::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); + } + + if (width < 1 || height < 1 || levels < 1) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (target == GL_TEXTURE_CUBE_MAP && width != height) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (levels != 1 && levels != gl::log2(std::max(width, height)) + 1) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + GLenum format = gl::GetFormat(internalformat); + GLenum type = gl::GetType(internalformat); + + if (format == GL_NONE || type == GL_NONE) + { + return gl::error(GL_INVALID_ENUM, false); + } + + const gl::Caps &caps = context->getCaps(); + + switch (target) + { + case GL_TEXTURE_2D: + if (static_cast(width) > caps.max2DTextureSize || + static_cast(height) > caps.max2DTextureSize) + { + return gl::error(GL_INVALID_VALUE, 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); + } + break; + default: + return gl::error(GL_INVALID_ENUM, false); + } + + if (levels != 1 && !context->getExtensions().textureNPOT) + { + if (!gl::isPow2(width) || !gl::isPow2(height)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + + switch (internalformat) + { + case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: + case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: + if (!context->getExtensions().textureCompressionDXT1) + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE: + if (!context->getExtensions().textureCompressionDXT3) + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + case GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE: + if (!context->getExtensions().textureCompressionDXT5) + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + case GL_RGBA32F_EXT: + case GL_RGB32F_EXT: + case GL_ALPHA32F_EXT: + case GL_LUMINANCE32F_EXT: + case GL_LUMINANCE_ALPHA32F_EXT: + if (!context->getExtensions().textureFloat) + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + case GL_RGBA16F_EXT: + case GL_RGB16F_EXT: + case GL_ALPHA16F_EXT: + case GL_LUMINANCE16F_EXT: + case GL_LUMINANCE_ALPHA16F_EXT: + if (!context->getExtensions().textureHalfFloat) + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + case GL_R8_EXT: + case GL_RG8_EXT: + case GL_R16F_EXT: + case GL_RG16F_EXT: + case GL_R32F_EXT: + case GL_RG32F_EXT: + if (!context->getExtensions().textureRG) + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + case GL_DEPTH_COMPONENT16: + case GL_DEPTH_COMPONENT32_OES: + case GL_DEPTH24_STENCIL8_OES: + if (!context->getExtensions().depthTextures) + { + return gl::error(GL_INVALID_ENUM, false); + } + if (target != GL_TEXTURE_2D) + { + return gl::error(GL_INVALID_OPERATION, false); + } + // ANGLE_depth_texture only supports 1-level textures + if (levels != 1) + { + return gl::error(GL_INVALID_OPERATION, false); + } + break; + default: + break; + } + + gl::Texture *texture = NULL; + switch(target) + { + case GL_TEXTURE_2D: + texture = context->getTexture2D(); + break; + case GL_TEXTURE_CUBE_MAP: + texture = context->getTextureCubeMap(); + break; + default: + UNREACHABLE(); + } + + if (!texture || texture->id() == 0) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (texture->isImmutable()) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + return true; +} + +// check for combinations of format and type that are valid for ReadPixels +bool ValidES2ReadFormatType(gl::Context *context, GLenum format, GLenum type) +{ + switch (format) + { + case GL_RGBA: + switch (type) + { + case GL_UNSIGNED_BYTE: + break; + default: + return false; + } + break; + case GL_BGRA_EXT: + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: + case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: + break; + default: + return false; + } + break; + case GL_RG_EXT: + case GL_RED_EXT: + if (!context->getExtensions().textureRG) + { + return false; + } + switch (type) + { + case GL_UNSIGNED_BYTE: + break; + default: + return false; + } + break; + + default: + return false; + } + return true; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/validationES2.h b/src/3rdparty/angle/src/libGLESv2/validationES2.h new file mode 100644 index 0000000000..e41e345876 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/validationES2.h @@ -0,0 +1,32 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// validationES2.h: Validation functions for OpenGL ES 2.0 entry point parameters + +#ifndef LIBGLESV2_VALIDATION_ES2_H +#define LIBGLESV2_VALIDATION_ES2_H + +namespace gl +{ + +class Context; + +bool ValidateES2TexImageParameters(gl::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, + 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, + GLsizei width, GLsizei height); + +bool ValidES2ReadFormatType(gl::Context *context, GLenum format, GLenum type); + +} + +#endif // LIBGLESV2_VALIDATION_ES2_H diff --git a/src/3rdparty/angle/src/libGLESv2/validationES3.cpp b/src/3rdparty/angle/src/libGLESv2/validationES3.cpp new file mode 100644 index 0000000000..a584a7127b --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/validationES3.cpp @@ -0,0 +1,682 @@ +#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 +// found in the LICENSE file. +// + +// validationES3.cpp: Validation functions for OpenGL ES 3.0 entry point parameters + +#include "libGLESv2/validationES3.h" +#include "libGLESv2/validationES.h" +#include "libGLESv2/Context.h" +#include "libGLESv2/Texture.h" +#include "libGLESv2/Framebuffer.h" +#include "libGLESv2/Renderbuffer.h" +#include "libGLESv2/formatutils.h" +#include "libGLESv2/main.h" +#include "libGLESv2/FramebufferAttachment.h" + +#include "common/mathutil.h" + +namespace gl +{ + +bool ValidateES3TexImageParameters(gl::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); + } + + // Validate image size + if (!ValidImageSize(context, target, level, width, height, depth)) + { + return gl::error(GL_INVALID_VALUE, false); + } + + // Verify zero border + if (border != 0) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (xoffset < 0 || yoffset < 0 || zoffset < 0 || + std::numeric_limits::max() - xoffset < width || + std::numeric_limits::max() - yoffset < height || + std::numeric_limits::max() - zoffset < depth) + { + return gl::error(GL_INVALID_VALUE, false); + } + + const gl::Caps &caps = context->getCaps(); + + gl::Texture *texture = NULL; + bool textureCompressed = false; + GLenum textureInternalFormat = GL_NONE; + GLint textureLevelWidth = 0; + GLint textureLevelHeight = 0; + GLint textureLevelDepth = 0; + switch (target) + { + case GL_TEXTURE_2D: + { + if (static_cast(width) > (caps.max2DTextureSize >> level) || + static_cast(height) > (caps.max2DTextureSize >> level)) + { + return gl::error(GL_INVALID_VALUE, false); + } + + gl::Texture2D *texture2d = context->getTexture2D(); + if (texture2d) + { + textureCompressed = texture2d->isCompressed(level); + textureInternalFormat = texture2d->getInternalFormat(level); + textureLevelWidth = texture2d->getWidth(level); + textureLevelHeight = texture2d->getHeight(level); + textureLevelDepth = 1; + texture = texture2d; + } + } + break; + + case GL_TEXTURE_CUBE_MAP_POSITIVE_X: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: + case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: + case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: + { + if (!isSubImage && width != height) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (static_cast(width) > (caps.maxCubeMapTextureSize >> level)) + { + return gl::error(GL_INVALID_VALUE, false); + } + + gl::TextureCubeMap *textureCube = context->getTextureCubeMap(); + if (textureCube) + { + textureCompressed = textureCube->isCompressed(target, level); + textureInternalFormat = textureCube->getInternalFormat(target, level); + textureLevelWidth = textureCube->getWidth(target, level); + textureLevelHeight = textureCube->getHeight(target, level); + textureLevelDepth = 1; + texture = textureCube; + } + } + break; + + case GL_TEXTURE_3D: + { + if (static_cast(width) > (caps.max3DTextureSize >> level) || + static_cast(height) > (caps.max3DTextureSize >> level) || + static_cast(depth) > (caps.max3DTextureSize >> level)) + { + return gl::error(GL_INVALID_VALUE, false); + } + + gl::Texture3D *texture3d = context->getTexture3D(); + if (texture3d) + { + textureCompressed = texture3d->isCompressed(level); + textureInternalFormat = texture3d->getInternalFormat(level); + textureLevelWidth = texture3d->getWidth(level); + textureLevelHeight = texture3d->getHeight(level); + textureLevelDepth = texture3d->getDepth(level); + texture = texture3d; + } + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + if (static_cast(width) > (caps.max2DTextureSize >> level) || + static_cast(height) > (caps.max2DTextureSize >> level) || + static_cast(depth) > (caps.maxArrayTextureLayers >> level)) + { + return gl::error(GL_INVALID_VALUE, false); + } + + gl::Texture2DArray *texture2darray = context->getTexture2DArray(); + if (texture2darray) + { + textureCompressed = texture2darray->isCompressed(level); + textureInternalFormat = texture2darray->getInternalFormat(level); + textureLevelWidth = texture2darray->getWidth(level); + textureLevelHeight = texture2darray->getHeight(level); + textureLevelDepth = texture2darray->getLayers(level); + texture = texture2darray; + } + } + break; + + default: + return gl::error(GL_INVALID_ENUM, false); + } + + if (!texture) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (texture->isImmutable() && !isSubImage) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + // Validate texture formats + GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat; + if (isCompressed) + { + if (!ValidCompressedImageSize(context, actualInternalFormat, width, height)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (!gl::IsFormatCompressed(actualInternalFormat)) + { + return gl::error(GL_INVALID_ENUM, false); + } + + if (target == GL_TEXTURE_3D) + { + return gl::error(GL_INVALID_OPERATION, 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())) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (target == GL_TEXTURE_3D && (format == GL_DEPTH_COMPONENT || format == GL_DEPTH_STENCIL)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + + // Validate sub image parameters + if (isSubImage) + { + if (isCompressed != textureCompressed) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (isCompressed) + { + if ((width % 4 != 0 && width != textureLevelWidth) || + (height % 4 != 0 && height != textureLevelHeight)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + + if (width == 0 || height == 0 || depth == 0) + { + return false; + } + + if (xoffset < 0 || yoffset < 0 || zoffset < 0) + { + return gl::error(GL_INVALID_VALUE, 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); + } + + if (xoffset + width > textureLevelWidth || + yoffset + height > textureLevelHeight || + zoffset + depth > textureLevelDepth) + { + return gl::error(GL_INVALID_VALUE, false); + } + } + + // Check for pixel unpack buffer related API errors + gl::Buffer *pixelUnpackBuffer = context->getState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER); + if (pixelUnpackBuffer != NULL) + { + // ...the data would be unpacked from the buffer object such that the memory reads required + // would exceed the data store size. + size_t widthSize = static_cast(width); + size_t heightSize = static_cast(height); + size_t depthSize = static_cast(depth); + GLenum sizedFormat = gl::IsSizedInternalFormat(actualInternalFormat) ? actualInternalFormat + : gl::GetSizedInternalFormat(actualInternalFormat, type); + + size_t pixelBytes = static_cast(gl::GetPixelBytes(sizedFormat)); + + 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); + } + + size_t copyBytes = widthSize * heightSize * depthSize * pixelBytes; + size_t offset = reinterpret_cast(pixels); + + if (!rx::IsUnsignedAdditionSafe(offset, copyBytes) || + ((offset + copyBytes) > static_cast(pixelUnpackBuffer->getSize()))) + { + // Overflow past the end of the buffer + return gl::error(GL_INVALID_OPERATION, 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)); + + if ((offset % dataBytesPerPixel) != 0) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + // ...the buffer object's data store is currently mapped. + if (pixelUnpackBuffer->isMapped()) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + + return true; +} + +bool ValidateES3CopyTexImageParameters(gl::Context *context, GLenum target, GLint level, GLenum internalformat, + bool isSubImage, GLint xoffset, GLint yoffset, GLint zoffset, + GLint x, GLint y, GLsizei width, GLsizei height, GLint border) +{ + GLenum textureInternalFormat; + if (!ValidateCopyTexImageParametersBase(context, target, level, internalformat, isSubImage, + xoffset, yoffset, zoffset, x, y, width, height, + border, &textureInternalFormat)) + { + return false; + } + + gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer(); + + if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE) + { + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + } + + if (context->getState().getReadFramebuffer()->id() != 0 && framebuffer->getSamples() != 0) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + gl::FramebufferAttachment *source = framebuffer->getReadColorbuffer(); + GLenum colorbufferInternalFormat = source->getInternalFormat(); + + if (isSubImage) + { + if (!gl::IsValidCopyTexImageCombination(textureInternalFormat, colorbufferInternalFormat, + context->getState().getReadFramebuffer()->id(), + context->getClientVersion())) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + else + { + if (!gl::IsValidCopyTexImageCombination(internalformat, colorbufferInternalFormat, + context->getState().getReadFramebuffer()->id(), + context->getClientVersion())) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + + // If width or height is zero, it is a no-op. Return false without setting an error. + return (width > 0 && height > 0); +} + +bool ValidateES3TexStorageParameters(gl::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); + } + + if (levels > gl::log2(std::max(std::max(width, height), depth)) + 1) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + const gl::Caps &caps = context->getCaps(); + + gl::Texture *texture = NULL; + switch (target) + { + case GL_TEXTURE_2D: + { + texture = context->getTexture2D(); + + if (static_cast(width) > caps.max2DTextureSize || + static_cast(height) > caps.max2DTextureSize) + { + return gl::error(GL_INVALID_VALUE, false); + } + } + break; + + case GL_TEXTURE_CUBE_MAP: + { + texture = context->getTextureCubeMap(); + + if (width != height) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (static_cast(width) > caps.maxCubeMapTextureSize) + { + return gl::error(GL_INVALID_VALUE, false); + } + } + break; + + case GL_TEXTURE_3D: + { + texture = context->getTexture3D(); + + if (static_cast(width) > caps.max3DTextureSize || + static_cast(height) > caps.max3DTextureSize || + static_cast(depth) > caps.max3DTextureSize) + { + return gl::error(GL_INVALID_VALUE, false); + } + } + break; + + case GL_TEXTURE_2D_ARRAY: + { + texture = context->getTexture2DArray(); + + if (static_cast(width) > caps.max2DTextureSize || + static_cast(height) > caps.max2DTextureSize || + static_cast(depth) > caps.maxArrayTextureLayers) + { + return gl::error(GL_INVALID_VALUE, false); + } + } + break; + + default: + return gl::error(GL_INVALID_ENUM, false); + } + + if (!texture || texture->id() == 0) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (texture->isImmutable()) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (!gl::IsValidInternalFormat(internalformat, context->getExtensions(), context->getClientVersion())) + { + return gl::error(GL_INVALID_ENUM, false); + } + + if (!gl::IsSizedInternalFormat(internalformat)) + { + return gl::error(GL_INVALID_ENUM, false); + } + + return true; +} + +bool ValidateFramebufferTextureLayer(const gl::Context *context, GLenum target, GLenum attachment, + GLuint texture, GLint level, GLint layer) +{ + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + if (layer < 0) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (!ValidateFramebufferTextureBase(context, target, attachment, texture, level)) + { + return false; + } + + const gl::Caps &caps = context->getCaps(); + if (texture != 0) + { + gl::Texture *tex = context->getTexture(texture); + ASSERT(tex); + + switch (tex->getTarget()) + { + case GL_TEXTURE_2D_ARRAY: + { + if (level > gl::log2(caps.max2DTextureSize)) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (static_cast(layer) >= caps.maxArrayTextureLayers) + { + return gl::error(GL_INVALID_VALUE, false); + } + + gl::Texture2DArray *texArray = static_cast(tex); + if (texArray->isCompressed(level)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + break; + + case GL_TEXTURE_3D: + { + if (level > gl::log2(caps.max3DTextureSize)) + { + return gl::error(GL_INVALID_VALUE, false); + } + + if (static_cast(layer) >= caps.max3DTextureSize) + { + return gl::error(GL_INVALID_VALUE, false); + } + + gl::Texture3D *tex3d = static_cast(tex); + if (tex3d->isCompressed(level)) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + break; + + default: + return gl::error(GL_INVALID_OPERATION, false); + } + } + + return true; +} + +bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type) +{ + switch (format) + { + case GL_RGBA: + switch (type) + { + case GL_UNSIGNED_BYTE: + break; + case GL_UNSIGNED_INT_2_10_10_10_REV: + if (internalFormat != GL_RGB10_A2) + { + return false; + } + break; + case GL_FLOAT: + if (gl::GetComponentType(internalFormat) != GL_FLOAT) + { + return false; + } + break; + default: + return false; + } + break; + case GL_RGBA_INTEGER: + switch (type) + { + case GL_INT: + if (gl::GetComponentType(internalFormat) != GL_INT) + { + return false; + } + break; + case GL_UNSIGNED_INT: + if (gl::GetComponentType(internalFormat) != GL_UNSIGNED_INT) + { + return false; + } + break; + default: + return false; + } + break; + case GL_BGRA_EXT: + switch (type) + { + case GL_UNSIGNED_BYTE: + case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT: + case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT: + break; + default: + return false; + } + break; + case GL_RG_EXT: + case GL_RED_EXT: + if (!context->getExtensions().textureRG) + { + return false; + } + switch (type) + { + case GL_UNSIGNED_BYTE: + break; + default: + return false; + } + break; + default: + return false; + } + return true; +} + +bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target, GLsizei numAttachments, + const GLenum* attachments) +{ + bool defaultFramebuffer = false; + + switch (target) + { + case GL_DRAW_FRAMEBUFFER: + case GL_FRAMEBUFFER: + defaultFramebuffer = context->getState().getDrawFramebuffer()->id() == 0; + break; + case GL_READ_FRAMEBUFFER: + defaultFramebuffer = context->getState().getReadFramebuffer()->id() == 0; + break; + default: + return gl::error(GL_INVALID_ENUM, false); + } + + for (int i = 0; i < numAttachments; ++i) + { + if (attachments[i] >= GL_COLOR_ATTACHMENT0 && attachments[i] <= GL_COLOR_ATTACHMENT15) + { + if (defaultFramebuffer) + { + return gl::error(GL_INVALID_ENUM, false); + } + + if (attachments[i] >= GL_COLOR_ATTACHMENT0 + context->getCaps().maxColorAttachments) + { + return gl::error(GL_INVALID_OPERATION, false); + } + } + else + { + switch (attachments[i]) + { + case GL_DEPTH_ATTACHMENT: + case GL_STENCIL_ATTACHMENT: + case GL_DEPTH_STENCIL_ATTACHMENT: + if (defaultFramebuffer) + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + case GL_COLOR: + case GL_DEPTH: + case GL_STENCIL: + if (!defaultFramebuffer) + { + return gl::error(GL_INVALID_ENUM, false); + } + break; + default: + return gl::error(GL_INVALID_ENUM, false); + } + } + } + + return true; +} + +bool ValidateClearBuffer(const gl::Context *context) +{ + if (context->getClientVersion() < 3) + { + return gl::error(GL_INVALID_OPERATION, false); + } + + const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer(); + if (!fbo || fbo->completeness() != GL_FRAMEBUFFER_COMPLETE) + { + return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); + } + + return true; +} + +} diff --git a/src/3rdparty/angle/src/libGLESv2/validationES3.h b/src/3rdparty/angle/src/libGLESv2/validationES3.h new file mode 100644 index 0000000000..4d068bd094 --- /dev/null +++ b/src/3rdparty/angle/src/libGLESv2/validationES3.h @@ -0,0 +1,40 @@ +// +// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// validationES3.h: Validation functions for OpenGL ES 3.0 entry point parameters + +#ifndef LIBGLESV2_VALIDATION_ES3_H +#define LIBGLESV2_VALIDATION_ES3_H + +namespace gl +{ + +class Context; + +bool ValidateES3TexImageParameters(gl::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 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, + GLsizei width, GLsizei height, GLsizei depth); + +bool ValidateFramebufferTextureLayer(const gl::Context *context, GLenum target, GLenum attachment, + GLuint texture, GLint level, GLint layer); + +bool ValidES3ReadFormatType(gl::Context *context, GLenum internalFormat, GLenum format, GLenum type); + +bool ValidateInvalidateFramebufferParameters(gl::Context *context, GLenum target, GLsizei numAttachments, + const GLenum* attachments); + +bool ValidateClearBuffer(const gl::Context *context); + +} + +#endif // LIBGLESV2_VALIDATION_ES3_H diff --git a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h index f725f55b57..7d06a6c70d 100644 --- a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h +++ b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h @@ -26,8 +26,6 @@ #ifndef THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_ #define THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_ -#include "GLSLANG/ShaderLang.h" - #include "compiler/translator/InfoSink.h" #include "compiler/translator/intermediate.h" diff --git a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h index c08f4f2585..adb52004e2 100644 --- a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h +++ b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h @@ -8,22 +8,8 @@ //----------------------------------------------------------------------------- // Platform-specific functions and macros -// Microsoft Visual Studio - -#if defined(_MSC_VER) - -typedef unsigned char uint8_t; -typedef unsigned long uint32_t; -typedef unsigned __int64 uint64_t; - -// Other compilers - -#else // defined(_MSC_VER) - #include -#endif // !defined(_MSC_VER) - //----------------------------------------------------------------------------- void MurmurHash3_x86_32 ( const void * key, int len, uint32_t seed, void * out ); diff --git a/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp new file mode 100644 index 0000000000..19a9644d70 --- /dev/null +++ b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.cpp @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2009 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#if _WIN32_WINNT_WINBLUE +#include +#endif + +namespace rx { + +#ifndef _WIN32_WINNT_WINBLUE +static bool IsWindowsVistaOrGreater() +{ + OSVERSIONINFOEXW osvi = { }; + osvi.dwOSVersionInfoSize = sizeof(osvi); + osvi.dwMajorVersion = HIBYTE(_WIN32_WINNT_VISTA); + osvi.dwMinorVersion = LOBYTE(_WIN32_WINNT_VISTA); + DWORDLONG condition = 0; + VER_SET_CONDITION(condition, VER_MAJORVERSION, VER_GREATER_EQUAL); + VER_SET_CONDITION(condition, VER_MINORVERSION, VER_GREATER_EQUAL); + return !!::VerifyVersionInfoW(&osvi, VER_MAJORVERSION | VER_MINORVERSION, condition); +} +#endif + +bool isWindowsVistaOrGreater() +{ + static bool initialized = false; + static bool cachedIsWindowsVistaOrGreater; + + if (!initialized) { + initialized = true; + cachedIsWindowsVistaOrGreater = IsWindowsVistaOrGreater(); + } + return cachedIsWindowsVistaOrGreater; +} + +} // namespace rx diff --git a/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h new file mode 100644 index 0000000000..65005ee9c6 --- /dev/null +++ b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2009 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SystemInfo_h +#define SystemInfo_h + +namespace rx { + +bool isWindowsVistaOrGreater(); + +} // namespace rx + +#endif // SystemInfo_h -- cgit v1.2.3